Home

Resume

Blog

Teikitu


/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
/*  »Project«   Teikitu Gaming System (TgS) (∂)
    »File«      TgS Effect - System.c
    »Author«    Andrew Aye (EMail: mailto:andrew.aye@gmail.com, Web: http://www.andrewaye.com)
    »Version«   4.51 / »GUID« A9981407-3EC9-42AF-8B6F-8BE6DD919615                                                                                                        */
/*   -------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
/*  Copyright: © 2002-2017, Andrew Aye.  All Rights Reserved.
    This software is free for non-commercial use.  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
      following conditions are met:
        Redistribution of source code must retain this copyright notice, this list of conditions and the following disclaimers.
        Redistribution in binary form must reproduce this copyright notice, this list of conditions and the following disclaimers in the documentation and other materials
          provided with the distribution.
    The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.
    The intellectual property rights of the algorithms used reside with Andrew Aye.
    You may not use this software, in whole or in part, in support of any commercial product without the express written consent of the author.
    There is no warranty or other guarantee of fitness of this software for any purpose. It is provided solely "as is".                                                   */
/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
/* == Effects =========================================================================================================================================================== */


/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */
/*  Private Functions                                                                                                                                                     */
/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */

TgEXTN TgVOID                               tgFX__Client__Process_ToClient_Command_Buffer( TgVOID );
TgEXTN TgVOID                               tgFX__Update__Group__Update_Command__Process_Command( C_ETgFX_COMMAND, CP_TgVOID );




/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */
/*  File Local Functions and Data                                                                                                                                         */
/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */

static TgVOID                               tgFX__Client__ToClient__Process_Command_Internal( P_TgUINT08, TgSIZE );

static TgVOID                               tgFX__Render__Allocate_Render_Buffers( TgVOID );
static TgRESULT                             tgFX__Render__Job__Allocate_Render_Buffers( PC_STg2_Job );
static TgVOID                               tgFX__Render__Submit_Job__Allocate_Render_Buffers( TgVOID );

static STg2_Job                             s_sFX__Job__Render__Allocate_Render_Buffers;



/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */
/*  Public Functions                                                                                                                                                      */
/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */

/* ---- tgFX__Client__Update_1 ------------------------------------------------------------------------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgFX__Client__Update_1( C_TgFLOAT32 fDT )
{
    TgVEC_M_F32_04                      vDT;

#if TgS_DEBUG_EFFECT
    TgBOOL                              bDisable;
    if ((TgTRUE == tgCN_Var_Query_Bool( &bDisable, g_tiFX_Debug__Disable_Update )) && (TgTRUE == bDisable))
        return;
/*# TgS_DEBUG_EFFECT */
#endif

    TgERROR( 0 == g_xiFX_Fence__UPDATE );
    TgERROR( 0 == g_xiFX_Fence__TO_CLIENT__COMMAND_QUEUE_FULL );
    TgERROR( 0 == g_xiFX_Fence__CLIENT_TO_UPDATE__PROCESS_COMMAND_STREAM );
    TgERROR( 0 == g_xiFX_Fence__CLIENT_TO_UPDATE__COMMAND_QUEUE_FULL );
    TgERROR( 0 == g_xiFX_Fence__SCENE_CULLING );
    TgERROR( 0 == g_xiFX_Fence__SCENE_BOUNDING_BOX );
    TgERROR( 0 == g_xiFX_Fence__RENDER_PROCESS_HEADERS );

    vDT = MS_SET1_F32_04( fDT );

    tgFX__Client__Collect_Collision_Results( TgFALSE );

    tgFX__Client__Submit_Job__Beam_Update( vDT, fDT, ETgFX_UPDATE__DEFAULT );
    tgFX__Client__Submit_Job__Billboard_Update( vDT, fDT, ETgFX_UPDATE__DEFAULT );
    tgFX__Client__Submit_Job__Decal_Update( vDT, fDT, ETgFX_UPDATE__DEFAULT );
    tgFX__Client__Submit_Job__Emitter_Update( vDT, fDT, ETgFX_UPDATE__DEFAULT );
    tgFX__Client__Submit_Job__GIB_Update( vDT, fDT, ETgFX_UPDATE__DEFAULT );
    tgFX__Client__Submit_Job__Glass_Update( vDT, fDT, ETgFX_UPDATE__DEFAULT );
    tgFX__Client__Submit_Job__Group_Update( vDT, fDT, ETgFX_UPDATE__DEFAULT );
    tgFX__Client__Submit_Job__Light_Update( vDT, fDT, ETgFX_UPDATE__DEFAULT );
    tgFX__Client__Submit_Job__Liquid_Update( vDT, fDT, ETgFX_UPDATE__DEFAULT );
    tgFX__Client__Submit_Job__Post_Update( vDT, fDT, ETgFX_UPDATE__DEFAULT );
    tgFX__Client__Submit_Job__Sound_Update( vDT, fDT, ETgFX_UPDATE__DEFAULT );
    tgFX__Client__Submit_Job__Trail_Update( vDT, fDT, ETgFX_UPDATE__DEFAULT );
}


/* ---- tgFX__Client__Update_2 ------------------------------------------------------------------------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgFX__Client__Update_2( C_TgFLOAT32 fDT )
{
    TgVEC_M_F32_04                      vDT;

    /* In case of overflow - flush the command queue.  Impact to state consistency is unknown. */
    if (0 != g_xiFX_Fence__CLIENT_TO_UPDATE__COMMAND_QUEUE_FULL)
    {
        tgFX__Client__Process_ToClient_Command_Buffer();
        TgVERIFY( 0 != tgAM32_XCHG( &g_xiFX_Fence__CLIENT_TO_UPDATE__COMMAND_QUEUE_FULL, 0 ) );
    };

#if TgS_DEBUG_EFFECT
    {
        TgBOOL                              bDisable;
        if ((TgTRUE == tgCN_Var_Query_Bool( &bDisable, g_tiFX_Debug__Disable_Update )) && (TgTRUE == bDisable))
            return;
    }
/*# TgS_DEBUG_EFFECT */
#endif

    tgFX__Client__Update_From_External_Module_Data( fDT );

    tgFX__Client__Collect_Collision_Results( TgFALSE );

    vDT = MS_SET1_F32_04( fDT );

    tgFX__Client__Submit_Job__Beam_Update( vDT, fDT, ETgFX_UPDATE__EXTERNAL );
    tgFX__Client__Submit_Job__Billboard_Update( vDT, fDT, ETgFX_UPDATE__EXTERNAL );
    tgFX__Client__Submit_Job__Decal_Update( vDT, fDT, ETgFX_UPDATE__EXTERNAL );
    tgFX__Client__Submit_Job__Emitter_Update( vDT, fDT, ETgFX_UPDATE__EXTERNAL );
    tgFX__Client__Submit_Job__GIB_Update( vDT, fDT, ETgFX_UPDATE__EXTERNAL );
    tgFX__Client__Submit_Job__Glass_Update( vDT, fDT, ETgFX_UPDATE__EXTERNAL );
    tgFX__Client__Submit_Job__Group_Update( vDT, fDT, ETgFX_UPDATE__EXTERNAL );
    tgFX__Client__Submit_Job__Light_Update( vDT, fDT, ETgFX_UPDATE__EXTERNAL );
    tgFX__Client__Submit_Job__Liquid_Update( vDT, fDT, ETgFX_UPDATE__EXTERNAL );
    tgFX__Client__Submit_Job__Post_Update( vDT, fDT, ETgFX_UPDATE__EXTERNAL );
    tgFX__Client__Submit_Job__Sound_Update( vDT, fDT, ETgFX_UPDATE__EXTERNAL );
    tgFX__Client__Submit_Job__Trail_Update( vDT, fDT, ETgFX_UPDATE__EXTERNAL );
}


/* ---- tgFX__Client__Update_Finish ------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgFX__Client__Update_Finish( TgVOID )
{
    tgFX__Client__Submit_Job__Beam_Update_Finish();
    tgFX__Client__Submit_Job__Billboard_Update_Finish();
    tgFX__Client__Submit_Job__Decal_Update_Finish();
    tgFX__Client__Submit_Job__Emitter_Update_Finish();
    tgFX__Client__Submit_Job__GIB_Update_Finish();
    tgFX__Client__Submit_Job__Glass_Update_Finish();
    tgFX__Client__Submit_Job__Group_Update_Finish();
    tgFX__Client__Submit_Job__Light_Update_Finish();
    tgFX__Client__Submit_Job__Liquid_Update_Finish();
    tgFX__Client__Submit_Job__Post_Update_Finish();
    tgFX__Client__Submit_Job__Sound_Update_Finish();
    tgFX__Client__Submit_Job__Trail_Update_Finish();
}


/* ---- tgFX__Client__Scene_Cull ---------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgFX__Client__Scene_Cull( PC_STg2_SE_Context psScene_Context, C_TgSINT32 iView_Index )
{
    TgERROR( 0 == g_xiFX_Fence__SCENE_CULLING );
    TgERROR( 0 == g_xiFX_Fence__SCENE_BOUNDING_BOX );

    /* In case of overflow - flush the command queue.  Impact to state consistency is unknown. */
    if (0 != g_xiFX_Fence__CLIENT_TO_UPDATE__COMMAND_QUEUE_FULL)
    {
        tgFX__Client__Process_ToClient_Command_Buffer();
        TgVERIFY( 0 != tgAM32_XCHG( &g_xiFX_Fence__CLIENT_TO_UPDATE__COMMAND_QUEUE_FULL, 0 ) );
    };

#if TgS_DEBUG_EFFECT
    {
        TgBOOL                              bDisable;
        if ((TgTRUE == tgCN_Var_Query_Bool( &bDisable, g_tiFX_Debug__Disable_Render )) && (TgTRUE == bDisable))
            return;
    }
/*# TgS_DEBUG_EFFECT */
#endif

    tgFX__Client__Submit_Job__Beam_Scene_Cull( psScene_Context, iView_Index );
    tgFX__Client__Submit_Job__Billboard_Scene_Cull( psScene_Context, iView_Index );
    tgFX__Client__Submit_Job__Decal_Scene_Cull( psScene_Context, iView_Index );
    tgFX__Client__Submit_Job__Emitter_Scene_Cull( psScene_Context, iView_Index );
    tgFX__Client__Submit_Job__GIB_Scene_Cull( psScene_Context, iView_Index );
    tgFX__Client__Submit_Job__Glass_Scene_Cull( psScene_Context, iView_Index );
    tgFX__Client__Submit_Job__Liquid_Scene_Cull( psScene_Context, iView_Index );
    tgFX__Client__Submit_Job__Post_Scene_Cull( psScene_Context, iView_Index );
    tgFX__Client__Submit_Job__Trail_Scene_Cull( psScene_Context, iView_Index );
}


/* ---- tgFX__Render__Update -------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgFX__Render__Update( PC_STg2_FX_Rnd_Output psRndOut )
{
    TgERROR( 0 == g_xiFX_Fence__RENDER_ALLOCATE );
    TgERROR( 0 == g_xiFX_Fence__RENDER_GENERATE );

#if TgS_DEBUG_EFFECT
    {
        TgBOOL                              bDisable;
        if ((TgTRUE == tgCN_Var_Query_Bool( &bDisable, g_tiFX_Debug__Disable_Render )) && (TgTRUE == bDisable))
            return;
    }
/*# TgS_DEBUG_EFFECT */
#endif

    g_uiParticle_Header_Index = (g_uiParticle_Header_Index + KTgFX_MAX_RENDER_INSTANCE) % (TgARRAY_COUNT( g_asParticle_Header ));

    tgFX__Render__Submit_Job__Beam_Process_Headers( psRndOut );
    tgFX__Render__Submit_Job__Billboard_Process_Headers( psRndOut );
    tgFX__Render__Submit_Job__Decal_Process_Headers( psRndOut );
    tgFX__Render__Submit_Job__Emitter_Process_Headers( psRndOut );
    tgFX__Render__Submit_Job__GIB_Process_Headers( psRndOut );
    tgFX__Render__Submit_Job__Glass_Process_Headers( psRndOut );
    tgFX__Render__Submit_Job__Liquid_Process_Headers( psRndOut );
    tgFX__Render__Submit_Job__Post_Process_Headers( psRndOut );
    tgFX__Render__Submit_Job__Trail_Process_Headers( psRndOut );

#if TgS_DEBUG_EFFECT
    {
        TgBOOL                              bDisable;
        if ((TgTRUE == tgCN_Var_Query_Bool( &bDisable, g_tiFX_Debug__Disable_Render_Buffer )) && (TgTRUE == bDisable))
            return;
    }
/*# TgS_DEBUG_EFFECT */
#endif

    tgFX__Render__Submit_Job__Allocate_Render_Buffers(); /* Determine the particles that will actually be generated based on memory requirements and priority */

    tgFX__Render__Submit_Job__Beam_Render_Generate( psRndOut );
    tgFX__Render__Submit_Job__Billboard_Render_Generate( psRndOut );
    tgFX__Render__Submit_Job__Decal_Render_Generate( psRndOut );
    tgFX__Render__Submit_Job__Emitter_Render_Generate( psRndOut );
    tgFX__Render__Submit_Job__GIB_Render_Generate( psRndOut );
    tgFX__Render__Submit_Job__Glass_Render_Generate( psRndOut );
    tgFX__Render__Submit_Job__Liquid_Render_Generate( psRndOut );
    tgFX__Render__Submit_Job__Post_Render_Generate( psRndOut );
    tgFX__Render__Submit_Job__Trail_Render_Generate( psRndOut );
}




/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */
/*  Private Functions                                                                                                                                                     */
/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */

/* ---- tgFX__Client__Process_ToClient_Command_Buffer ------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgFX__Client__Process_ToClient_Command_Buffer( TgVOID )
{
    tgFX__Client__ToClient__Process_Command_Internal( g_asFX_Command__Beam__ToClient, g_uiFX_Command__Beam__ToClient_Offset );
    tgFX__Client__ToClient__Process_Command_Internal( g_asFX_Command__Billboard__ToClient, g_uiFX_Command__Billboard__ToClient_Offset );
    tgFX__Client__ToClient__Process_Command_Internal( g_asFX_Command__Decal__ToClient, g_uiFX_Command__Decal__ToClient_Offset );
    tgFX__Client__ToClient__Process_Command_Internal( g_asFX_Command__Emitter__ToClient, g_uiFX_Command__Emitter__ToClient_Offset );
    tgFX__Client__ToClient__Process_Command_Internal( g_asFX_Command__GIB__ToClient, g_uiFX_Command__GIB__ToClient_Offset );
    tgFX__Client__ToClient__Process_Command_Internal( g_asFX_Command__Glass__ToClient, g_uiFX_Command__Glass__ToClient_Offset );
    tgFX__Client__ToClient__Process_Command_Internal( g_asFX_Command__Group__ToClient, g_uiFX_Command__Group__ToClient_Offset );
    tgFX__Client__ToClient__Process_Command_Internal( g_asFX_Command__Liquid__ToClient, g_uiFX_Command__Liquid__ToClient_Offset );
    tgFX__Client__ToClient__Process_Command_Internal( g_asFX_Command__Light__ToClient, g_uiFX_Command__Light__ToClient_Offset );
    tgFX__Client__ToClient__Process_Command_Internal( g_asFX_Command__Sound__ToClient, g_uiFX_Command__Sound__ToClient_Offset );
    tgFX__Client__ToClient__Process_Command_Internal( g_asFX_Command__Post__ToClient, g_uiFX_Command__Post__ToClient_Offset );
    tgFX__Client__ToClient__Process_Command_Internal( g_asFX_Command__Trail__ToClient, g_uiFX_Command__Trail__ToClient_Offset );
}


/* ---- tgFX__Client__Update_From_External_Module_Data ------------------------------------------------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgFX__Client__Update_From_External_Module_Data( C_TgFLOAT32 fClient_Time_Total )
{
    TgFX_CLIENT_INST_ID                 tiPrev_Client;
    TgFX_CLIENT_INST_ID                 tiCurrent_Client;

    tiPrev_Client = KTgFX_CLIENT_INST_ID__INVALID;
    tiCurrent_Client = g_atiFX__Client__Update__Head[ETgFX_UPDATE__EXTERNAL];

    while (TgFALSE != tgFX_CLIENT_INST_ID_Is_Valid( tiCurrent_Client ))
    {
        TgVEC_F32_04                        vPos_W;
        TgVEC_F32_04                        qRot_W;

        /* Pull update from attachment - kill effects with in valid attachments */
        if (TgFAILED( tgAttachment__Query_Attachment_W( g_asFX_Effect[tiCurrent_Client.m.iI].m_tiAttachment, fClient_Time_Total, &vPos_W, &qRot_W ) ))
        {
            /* #REVIEW: Attachment is no longer valid - do we kill the effect, move it into the default update list, or leave it */
            g_asFX_Effect[tiCurrent_Client.m.iI].m_tiAttachment = KTgATTACHMENT_ID__INVALID;
            tgFX__Client__Kill( tiCurrent_Client );
        }
        else
        {
            tgFX__Client__Set_Rotation_From_External_Update( g_asFX_Effect[tiCurrent_Client.m.iI].m_tiClient, qRot_W.m_mData );
            tgFX__Client__Set_Position_From_External_Update( g_asFX_Effect[tiCurrent_Client.m.iI].m_tiClient, vPos_W.m_mData );
        };

        tiPrev_Client = tiCurrent_Client;
        tiCurrent_Client = g_asFX_Effect[tiCurrent_Client.m.iI].m_tiUpdate_Next;
    };
}


/* ---- tgFX__Client__Collect_Collision_Results ------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgFX__Client__Collect_Collision_Results( C_TgBOOL UNUSED_PARAM bWait )
{
    /* #TODO: Complete tgFX__Client__Collect_Collision_Results */
}


/* ---- tgFX__Client__Queue_Update_Command ------------------------------------------------------------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgBOOL tgFX__Client__Queue_Update_Command( C_ETgFX__EFFECT enEffect, C_ETgFX_COMMAND enCommand, CP_TgVOID pData )
{
    TgBOOL                              bResult;

    TgPARAM_CHECK( ETgFX_COMMAND__CLIENT_TO_UPDATE__BEGIN <= enCommand && ETgFX_COMMAND__CLIENT_TO_UPDATE__END >= enCommand );

    if (ETgFX__GROUP == enEffect && ETgFX_COMMAND__CLIENT_TO_UPDATE__KILL != enCommand)
    {
        tgFX__Update__Group__Update_Command__Process_Command( enCommand, pData );
        return (TgTRUE);
    };

    bResult = TgFALSE;
    switch (enEffect)
    {
        case ETgFX__INVALID:   bResult = tgFX__Client__Emitter_Update_Command( enCommand, pData ); break;
        case ETgFX__BEAM:      bResult = tgFX__Client__Beam_Update_Command( enCommand, pData ); break;
        case ETgFX__BILLBOARD: bResult = tgFX__Client__Billboard_Update_Command( enCommand, pData ); break;
        case ETgFX__DECAL:     bResult = tgFX__Client__Decal_Update_Command( enCommand, pData ); break;
        case ETgFX__EMITTER:   bResult = tgFX__Client__Emitter_Update_Command( enCommand, pData ); break;
        case ETgFX__GIB:       bResult = tgFX__Client__GIB_Update_Command( enCommand, pData ); break;
        case ETgFX__GLASS:     bResult = tgFX__Client__Glass_Update_Command( enCommand, pData ); break;
        case ETgFX__GROUP:     bResult = tgFX__Client__Group_Update_Command( enCommand, pData ); break;
        case ETgFX__LIGHT:     bResult = tgFX__Client__Light_Update_Command( enCommand, pData ); break;
        case ETgFX__LIQUID:    bResult = tgFX__Client__Liquid_Update_Command( enCommand, pData ); break;
        case ETgFX__POST:      bResult = tgFX__Client__Post_Update_Command( enCommand, pData ); break;
        case ETgFX__SOUND:     bResult = tgFX__Client__Sound_Update_Command( enCommand, pData ); break;
        case ETgFX__TRAIL:     bResult = tgFX__Client__Trail_Update_Command( enCommand, pData ); break;

        case ETgFX__EFFECT_MAX:
        default: TgS_NO_DEFAULT( break );
    };

    return (bResult);
}




/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */
/*  File Local Functions                                                                                                                                                  */
/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */

/* ---- tgFX__Client__ToClient__Process_Command_Internal ---------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
static TgVOID tgFX__Client__ToClient__Process_Command_Internal( P_TgUINT08 puiCommand_Stream, TgSIZE uiOffset )
{
    TgSIZE                              uiBuffer_Size;
    TgSIZE                              uiIndex;
    ETgFX_COMMAND                       enCommand;
    TgSINT32                            iEffect_Index;

    PROFILE_START( FX_COMMANDS__CLIENT );

    uiBuffer_Size = uiOffset;
    TgERROR( uiBuffer_Size <= ETgFX_COMMAND__TO_CLIENT__BYTE_MAX );
    for (uiIndex = 0; uiIndex < uiBuffer_Size; )
    {
        union
        {
            CP_TgUINT08                         pui;
            P_ETgFX_COMMAND                     pen;
        }                                   sCommand;
        
        sCommand.pui = puiCommand_Stream;
        enCommand = *sCommand.pen;
        uiIndex += g_uiFX_Command_Size[enCommand];

        switch (enCommand)
        {
            case ETgFX_COMMAND__UPDATE_TO_CLIENT__CREATE:
            {
                union
                {
                    CP_TgUINT08                         pui;
                    P_STg2_FX_Command__Client__Create   ps;
                }                                   sCommand_Payload;
                
                sCommand_Payload.pui = puiCommand_Stream;
                tgFX__Client__Inst_FX_Hash( sCommand_Payload.ps->m_uiHash, &sCommand_Payload.ps->m_sInstance, TgTRUE );
                break;
            };

            case ETgFX_COMMAND__UPDATE_TO_CLIENT__FREE:
            {
                union
                {
                    CP_TgUINT08                         pui;
                    P_STg2_FX_Command__Client__Free     ps;
                }                                   sCommand_Payload;
                
                sCommand_Payload.pui = puiCommand_Stream;
                iEffect_Index = sCommand_Payload.ps->m_tiClient.m.iI;
                if (g_asFX_Effect[iEffect_Index].m_tiClient.m_iKI == sCommand_Payload.ps->m_tiClient.m_iKI)
                {
                    tgFX__Client__Free_Internal( iEffect_Index );
                };

                break;
            };

            case ETgFX_COMMAND__UPDATE_TO_CLIENT__NOTIFY:
            {
                union
                {
                    CP_TgUINT08                         pui;
                    P_STg2_FX_Command__Notify           ps;
                }                                   sCommand_Payload;
                
                sCommand_Payload.pui = puiCommand_Stream;
                switch (sCommand_Payload.ps->m_uiMessage)
                {
                    case ETgFX_NOTIFY__FRAME_COMPLETE:
                        tgAMXX_INC( (TgATOMIC_UINTXX*)(sCommand_Payload.ps->m_pNotify) );
                        break;
                    default:
                        TgS_NO_DEFAULT( break );
                };
                break;
            };

            case ETgFX_COMMAND__CLIENT_TO_UPDATE__BEGIN:
            case ETgFX_COMMAND__CLIENT_TO_UPDATE__CREATE:
            case ETgFX_COMMAND__CLIENT_TO_UPDATE__KILL:
            case ETgFX_COMMAND__CLIENT_TO_UPDATE__STOP:
            case ETgFX_COMMAND__CLIENT_TO_UPDATE__POSITION_SET:
            case ETgFX_COMMAND__CLIENT_TO_UPDATE__POSITION_UPDATE_FROM_PARENT:
            case ETgFX_COMMAND__CLIENT_TO_UPDATE__ROTATION_SET:
            case ETgFX_COMMAND__CLIENT_TO_UPDATE__ROTATION_UPDATE_FROM_PARENT:
            case ETgFX_COMMAND__CLIENT_TO_UPDATE__SPIN:
            case ETgFX_COMMAND__CLIENT_TO_UPDATE__VISIBLE:
            case ETgFX_COMMAND__SCENE_TO_RENDER__PATCH_CONTEXT:
            case ETgFX_COMMAND__MAX:
            default:
                TgS_NO_DEFAULT( break );
        };
    };
    PROFILE_STOP( FX_COMMANDS__CLIENT );
}


/* ---- tgFX__Render__Allocate_Render_Buffers --------------------------------------------------------------------------------------------------------------------------- */
/* Priority allocate the buffer memory based on heuristic */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
static TgVOID tgFX__Render__Allocate_Render_Buffers( TgVOID )
{
    /* #TODO: Complete tgFX__Render__Allocate_Render_Buffers */
}


/* ---- tgFX__Render__Job__Allocate_Render_Buffers ---------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
static TgRESULT tgFX__Render__Job__Allocate_Render_Buffers( PC_STg2_Job UNUSED_PARAM psJob )
{
    tgFX__Render__Allocate_Render_Buffers();
    return (KTgS_OK);
}


/* ---- tgFX__Render__Submit_Job__Allocate_Render_Buffers --------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
static TgVOID tgFX__Render__Submit_Job__Allocate_Render_Buffers( TgVOID )
{
    TgERROR( 0 == g_xiFX_Fence__RENDER_ALLOCATE );

    tgAM32_INC( &g_xiFX_Fence__RENDER_ALLOCATE );
    memset( &s_sFX__Job__Render__Allocate_Render_Buffers, 0, sizeof( STg2_Job ) );
    s_sFX__Job__Render__Allocate_Render_Buffers.m_pfnExecute = tgFX__Render__Job__Allocate_Render_Buffers;
    s_sFX__Job__Render__Allocate_Render_Buffers.m_pxiFinish = &g_xiFX_Fence__RENDER_ALLOCATE;

    tgJM_Queue_Job( g_sJob_Queue__Render_High, &s_sFX__Job__Render__Allocate_Render_Buffers );
}