Home

Resume

Blog

Teikitu


/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
/*  »Project«   Teikitu Gaming System (TgS) (∂)
    »File«      TgS Effect - Effect - Render.c_inc
    »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 =========================================================================================================================================================== */
#if T_EFFECT_RENDER


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

static TgSIZE                               T_NAME(tgFX__Render__, _Render_Memory_Particle_00)( T_NAME(P_STg2_FX__,) );
static TgSIZE                               T_NAME(tgFX__Render__, _Render_Memory_Particle_01)( T_NAME(P_STg2_FX__,) );
static TgUINT32                             T_NAME(tgFX__Render__, _Render_Generate_Particle_00)( PC_STg2_FX_Rnd_Output, PC_STg2_RN_Particle_Header, T_NAME(P_STg2_FX__,) );
static TgUINT32                             T_NAME(tgFX__Render__, _Render_Generate_Particle_01)( PC_STg2_FX_Rnd_Output, PC_STg2_RN_Particle_Header, T_NAME(P_STg2_FX__,) );




/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */
/*  Exported Functions                                                                                                                                                    */
/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */

TgEXTN TgVOID                               T_NAME(tgFX__Client__, _Init_Render)( TgVOID );
TgEXTN TgVOID                               T_NAME(tgFX__Client__, _Boot_Render)( TgVOID );




/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */
/*  Private Functions and Data                                                                                                                                            */
/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */

TgEXTN TgFX_DATA_INST_ID                    T_NAME(tgFX__, _Reset_Scene_Particle_Head)( C_ETgFX_UPDATE );
TgEXTN TgFX_DATA_INST_ID                    T_NAME(tgFX__, _Reset_Scene_Mesh_Head)( C_ETgFX_UPDATE );
TgEXTN TgSIZE                               T_NAME(tgFX__, _Scene_Active_Count)( C_ETgFX_UPDATE );

TgEXTN T_NAME(STg2_FX__,)                   T_NAME(g_asFX__,)[T_TYPE(KTgFX_MAX_,)];




/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */
/*  Profile Markers                                                                                                                                                       */
/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */

static PROFILE_ARRAY_DEFINE( ETgFX_UPDATE__MAX, T_TYPE(FX_, _RENDER__PROCESS_HEADERS) );
static PROFILE_DEFINE( T_TYPE(FX_, _RENDER__PROCESS_HEADERS_TOTAL) );
static PROFILE_DEFINE( T_TYPE(FX_, _RENDER__GENERATE) );




/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */
/*  File Local Types                                                                                                                                                      */
/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */

TgTYPE_STRUCT_ALIGN(STg2_FX_Job__Process_Headers,16,)
{
    P_STg2_FX_Rnd_Output                        m_psRndOut;
    ETgFX_UPDATE                                m_enUpdate;
    TgUINT32                                    m_uiPad;
};
TgCOMPILER_ASSERT( sizeof( STg2_FX_Job__Process_Headers ) <= KTgJOB_DATA_SIZE, 0 );

TgTYPE_STRUCT_ALIGN(STg2_FX_Job__Render_Generate,16,)
{
    P_STg2_FX_Rnd_Output                        m_psRndOut;
    TgUINT32                                    m_uiPad0[2];
};
TgCOMPILER_ASSERT( sizeof( STg2_FX_Job__Render_Generate ) <= KTgJOB_DATA_SIZE, 0 );




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

TgFORCEINLINE TgVOID                        T_NAME(tgFX__Render__, _Init_Header)( P_STg2_RN_Particle_Header, T_NAME(P_STg2_FX__,) );
static TgVOID                               T_NAME(tgFX__Render__, _Process_Headers)( PC_STg2_FX_Rnd_Output, C_ETgFX_UPDATE );
static TgRESULT                             T_NAME(tgFX__Render__Job__, _Process_Headers)( PC_STg2_Job );

static TgVOID                               T_NAME(tgFX__Render__, _Render_Generate)( PC_STg2_FX_Rnd_Output );
static TgRESULT                             T_NAME(tgFX__Render__Job__, _Render_Generate)( PC_STg2_Job );

static TgATOMIC_SINT32                      T_NAME(s_axiFX__Render__Fence__, _Process_Headers)[ETgFX_UPDATE__MAX];
static STg2_Job                             T_NAME(s_asFX__Render__Job__, _Process_Headers)[ETgFX_UPDATE__MAX];
static TgATOMIC_SINT32                      T_NAME(s_xiFX__Render__Fence__, _Process_Headers_Total);

static TgATOMIC_SINT32                      T_NAME(s_xiFX__Render__Fence__, _Render_Generate);
static STg2_Job                             T_NAME(s_sFX__Render__Job__, _Render_Generate);

TgCOMPILER_ASSERT( sizeof( STg2_UTM_Node ) <= sizeof( T_NAME(STg2_FX__,) ), 0 );

static TgFX_DATA_INST_ID                    T_NAME(s_atiFX__, __Render_Header__Head)[ETgFX_UPDATE__MAX];
static TgSINT32                             T_NAME(s_niFX__, __Render_Header__Active);
static TgFX_DATA_INST_ID                    T_NAME(s_atiFX__, __Render_Generate__Head);
static TgSINT32                             T_NAME(s_niFX__, __Render_Generate__Active);




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

/* ---- tgFX__Client__, _Init_Render ------------------------------------------------------------------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID T_NAME(tgFX__Client__, _Init_Render)( TgVOID )
{
    TgSINT32                            iIndex;

    PROFILE_ARRAY_INIT( 0, TgT("DEFAULT"), T_TYPE(FX_, _RENDER__PROCESS_HEADERS) );
    PROFILE_ARRAY_INIT( 1, TgT("EXTERNAL"), T_TYPE(FX_, _RENDER__PROCESS_HEADERS) );
    PROFILE_INIT( T_TYPE(FX_, _RENDER__PROCESS_HEADERS_TOTAL) );

    PROFILE_INIT( T_TYPE(FX_, _RENDER__GENERATE) );

    for (iIndex = 0; iIndex < ETgFX_UPDATE__MAX; ++iIndex)
    {
        T_NAME(s_axiFX__Render__Fence__, _Process_Headers)[iIndex] = 0;
        memset( T_NAME(s_asFX__Render__Job__, _Process_Headers) + iIndex, 0, sizeof( STg2_Job ) );
    };
    T_NAME(s_xiFX__Render__Fence__, _Process_Headers_Total) = 0;
    T_NAME(s_xiFX__Render__Fence__, _Render_Generate) = 0;
    memset( & T_NAME(s_sFX__Render__Job__, _Render_Generate), 0, sizeof( STg2_Job ) );

    for (iIndex = 0; iIndex < ETgFX_UPDATE__MAX; ++iIndex)
    {
        T_NAME(s_atiFX__, __Render_Header__Head)[iIndex] = KTgFX_DATA_INST_ID__INVALID;
    };
    T_NAME(s_niFX__, __Render_Header__Active) = 0;
    T_NAME(s_atiFX__, __Render_Generate__Head) = KTgFX_DATA_INST_ID__INVALID;
    T_NAME(s_niFX__, __Render_Generate__Active) = 0;
}


/* ---- tgFX__Client__, _Boot ------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID T_NAME(tgFX__Client__, _Boot_Render)( TgVOID )
{
    T_NAME(s_asFX__Render__Job__, _Process_Headers)[ETgFX_UPDATE__DEFAULT].m_pfnExecute = T_NAME(tgFX__Render__Job__, _Process_Headers);
    T_NAME(s_asFX__Render__Job__, _Process_Headers)[ETgFX_UPDATE__DEFAULT].m_pxiFinish = T_NAME(s_axiFX__Render__Fence__, _Process_Headers) + ETgFX_UPDATE__DEFAULT;
    T_NAME(s_asFX__Render__Job__, _Process_Headers)[ETgFX_UPDATE__EXTERNAL].m_pfnExecute = T_NAME(tgFX__Render__Job__, _Process_Headers);
    T_NAME(s_asFX__Render__Job__, _Process_Headers)[ETgFX_UPDATE__EXTERNAL].m_pxiFinish = T_NAME(s_axiFX__Render__Fence__, _Process_Headers) + ETgFX_UPDATE__EXTERNAL;

    T_NAME(s_sFX__Render__Job__, _Render_Generate).m_pfnExecute = T_NAME(tgFX__Render__Job__, _Render_Generate);
    T_NAME(s_sFX__Render__Job__, _Render_Generate).m_pxiTrigger = & T_NAME(s_xiFX__Render__Fence__, _Process_Headers_Total);
    T_NAME(s_sFX__Render__Job__, _Render_Generate).m_pxiFinish = & T_NAME(s_xiFX__Render__Fence__, _Render_Generate);
}


/* ---- tgFX__Render__Submit_Job__, _Process_Headers -------------------------------------------------------------------------------------------------------------------- */
/* Patch Context Buffer, Map Context to Particle Buffer, and compute memory requirements                                                                                  */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID T_NAME(tgFX__Render__Submit_Job__, _Process_Headers)( PC_STg2_FX_Rnd_Output psRndOut )
{
    union
    {
        P_STg2_FX_Job__Process_Headers      psJob;
        P_TgUINT08                          pui;
    }                                   psData;

    psData.pui = T_NAME(s_asFX__Render__Job__, _Process_Headers)[ETgFX_UPDATE__DEFAULT].m_auiData;
    psData.psJob->m_psRndOut = psRndOut;
    psData.psJob->m_enUpdate = ETgFX_UPDATE__DEFAULT;

    tgAM32_INC( &g_xiFX_Fence__RENDER_PROCESS_HEADERS );
    tgAM32_INC( &T_NAME(s_xiFX__Render__Fence__, _Process_Headers_Total) );
    tgAM32_INC( T_NAME(s_axiFX__Render__Fence__, _Process_Headers) + ETgFX_UPDATE__DEFAULT );
    tgJM_Queue_Job( g_sJob_Queue__Render_Normal, T_NAME(s_asFX__Render__Job__, _Process_Headers) + ETgFX_UPDATE__DEFAULT );

    psData.pui = T_NAME(s_asFX__Render__Job__, _Process_Headers)[ETgFX_UPDATE__EXTERNAL].m_auiData;
    psData.psJob->m_psRndOut = psRndOut;
    psData.psJob->m_enUpdate = ETgFX_UPDATE__EXTERNAL;

    tgAM32_INC( &g_xiFX_Fence__RENDER_PROCESS_HEADERS );
    tgAM32_INC( &T_NAME(s_xiFX__Render__Fence__, _Process_Headers_Total) );
    tgAM32_INC( T_NAME(s_axiFX__Render__Fence__, _Process_Headers) + ETgFX_UPDATE__EXTERNAL );
    tgJM_Queue_Job( g_sJob_Queue__Render_Normal, T_NAME(s_asFX__Render__Job__, _Process_Headers) + ETgFX_UPDATE__EXTERNAL );
}


/* ---- tgFX__Render__Submit_Job__, _Render_Generate -------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID T_NAME(tgFX__Render__Submit_Job__, _Render_Generate)( PC_STg2_FX_Rnd_Output psRndOut)
{
    union
    {
        P_STg2_FX_Job__Render_Generate      psJob;
        P_TgUINT08                          pui;
    }                                   psData;

    psData.pui = T_NAME(s_sFX__Render__Job__, _Render_Generate).m_auiData;
    psData.psJob->m_psRndOut = psRndOut;

    tgAM32_INC( &g_xiFX_Fence__RENDER_GENERATE );
    tgAM32_INC( &T_NAME(s_xiFX__Render__Fence__, _Render_Generate) );
    tgJM_Queue_Job( g_sJob_Queue__Render_Normal, & T_NAME(s_sFX__Render__Job__, _Render_Generate) );
}




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

/* ---- tgFX__Render__, _Process_Headers -------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgFORCEINLINE TgVOID T_NAME(tgFX__Render__, _Init_Header)( P_STg2_RN_Particle_Header psFX_Header, T_NAME(P_STg2_FX__,) psEffect )
{
#if TgS_DEBUG_EFFECT && TgCOMPILE_RENDER_DEBUG_OUTPUT
    {
        TgBOOL                              bDraw;
        if ((TgTRUE == tgCN_Var_Query_Bool( &bDraw, T_NAME(g_tiFX_Debug__, __Draw_BA) )) && (TgTRUE == bDraw))
            tgRN_DBG_Wireframe_BoxAA( KTg_WHITE_709_U32, psEffect->m_vBA_Max_W, psEffect->m_vBA_Min_W );
        else if ((TgTRUE == tgCN_Var_Query_Bool( &bDraw, g_tiFX_Debug__Draw_BA )) && (TgTRUE == bDraw))
            tgRN_DBG_Wireframe_BoxAA( KTg_WHITE_709_U32, psEffect->m_vBA_Max_W, psEffect->m_vBA_Min_W );
    }
/*# TgS_DEBUG_EFFECT && TgCOMPILE_RENDER_DEBUG_OUTPUT */
#endif

    psFX_Header->m_iIndex_In_SE_Context = psEffect->m_iIndex_In_SE_Context;
    psFX_Header->m_tiMesh_Set = psEffect->m_tiMesh_Set;
    psFX_Header->m_tiMaterial = psEffect->m_tiMaterial;
    psFX_Header->m_enPrimitive = T_EFFECT_RENDER_PRIMITIVE_TYPE;
    psFX_Header->m_enVertex = psEffect->m_enVertex;
    psFX_Header->m_uiBuffer_Offset = 0;

    if (ETgRN_VERTEX_PARTICLE_00 == psEffect->m_enVertex)
    {
        psFX_Header->m_nuiVertex = T_NAME(tgFX__Render__, _Render_Memory_Particle_00)( psEffect );
        psFX_Header->m_uiBuffer_Size = psFX_Header->m_nuiVertex * sizeof( STg2_RN_Vertex_Particle_00 );
    }
    else if (ETgRN_VERTEX_PARTICLE_01 == psEffect->m_enVertex)
    {
        psFX_Header->m_nuiVertex = T_NAME(tgFX__Render__, _Render_Memory_Particle_01)( psEffect );
        psFX_Header->m_uiBuffer_Size = psFX_Header->m_nuiVertex * sizeof( STg2_RN_Vertex_Particle_01 );
    }
    else
    {
        psFX_Header->m_nuiVertex = 0;
        psFX_Header->m_uiBuffer_Size = 0;
    };
}


/* ---- tgFX__Render__, _Process_Headers -------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
static TgVOID T_NAME(tgFX__Render__, _Process_Headers)( PC_STg2_FX_Rnd_Output psRndOut, C_ETgFX_UPDATE enUpdate )
{
    TgSIZE                              uiHeader_Count;
    TgSIZE                              uiHeader_Index;
    P_STg2_RN_Particle_Header           psFX_Header;
    TgFX_DATA_INST_ID                   tiActive;
    T_NAME(P_STg2_FX__,)                psEffect;

    PROFILE_ARRAY_START( enUpdate, T_TYPE(FX_, _RENDER__PROCESS_HEADERS) );
    PROFILE_START( FX_RENDER_PROCESS_COMMANDS );
    TgERROR( g_uiParticle_Header_Index + KTgFX_MAX_RENDER_INSTANCE < TgARRAY_COUNT( g_asParticle_Header ) );

    /* Allocate an effect render data for the frame */
    uiHeader_Count = T_NAME(tgFX__, _Scene_Active_Count)( enUpdate );
    uiHeader_Index = tgAMXX_XADD( &psRndOut->m_nuiFX_Header, uiHeader_Count );
    TgERROR( uiHeader_Index + uiHeader_Count < (TgSIZE)KTgFX_MAX_RENDER_INSTANCE );
    psFX_Header = psRndOut->m_psFX_Header + uiHeader_Index;

    tiActive = T_NAME(tgFX__, _Reset_Scene_Particle_Head)( enUpdate );
    T_NAME(s_niFX__, __Render_Header__Active) = 0;
    while (TgFALSE != tgFX_DATA_INST_ID_Is_Valid( tiActive ))
    {
        psEffect = T_NAME(g_asFX__,) + tiActive.m.iI;
        T_NAME(tgFX__Render__, _Init_Header)( psFX_Header, psEffect );
        psRndOut->m_puiContext_To_Particle_Header_Index[psEffect->m_iIndex_In_SE_Context] = uiHeader_Index;
        --uiHeader_Count;
        ++psFX_Header;
        ++uiHeader_Index;
        tiActive = psEffect->m_tiNext[ETgFX_NEXT__SCENE];
        psEffect->m_tiNext[ETgFX_NEXT__SCENE] = KTgFX_DATA_INST_ID__INVALID;
        ++T_NAME(s_niFX__, __Render_Header__Active);
        psEffect->m_tiNext[ETgFX_NEXT__RENDER] = T_NAME(s_atiFX__, __Render_Header__Head)[enUpdate];
        T_NAME(s_atiFX__, __Render_Header__Head)[enUpdate] = psEffect->m_tiData;
    };

    tiActive = T_NAME(tgFX__, _Reset_Scene_Mesh_Head)( enUpdate );
    while (TgFALSE != tgFX_DATA_INST_ID_Is_Valid( tiActive ))
    {
        psEffect = T_NAME(g_asFX__,) + tiActive.m.iI;
        T_NAME(tgFX__Render__, _Init_Header)( psFX_Header, psEffect );
        psRndOut->m_puiContext_To_Particle_Header_Index[psEffect->m_iIndex_In_SE_Context] = uiHeader_Index;
        --uiHeader_Count;
        ++psFX_Header;
        ++uiHeader_Index;
        tiActive = psEffect->m_tiNext[ETgFX_NEXT__SCENE];
        psEffect->m_tiNext[ETgFX_NEXT__SCENE] = KTgFX_DATA_INST_ID__INVALID;
    };

    TgERROR( 0 == uiHeader_Count );

    PROFILE_STOP( FX_RENDER_PROCESS_COMMANDS );
    PROFILE_ARRAY_STOP( enUpdate, T_TYPE(FX_, _RENDER__PROCESS_HEADERS) );
}


/* ---- tgFX__Render__Job__, _Process_Headers --------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
static TgRESULT T_NAME(tgFX__Render__Job__, _Process_Headers)( PC_STg2_Job psJob )
{
    union
    {
        P_STg2_FX_Job__Process_Headers      psProcess_Headers;
        P_TgUINT08                          pui;
    }                                   sUnion;

    sUnion.pui = psJob->m_auiData;

    T_NAME(tgFX__Render__, _Process_Headers)( sUnion.psProcess_Headers->m_psRndOut, sUnion.psProcess_Headers->m_enUpdate );

    tgAM32_DEC( &g_xiFX_Fence__RENDER_PROCESS_HEADERS );
    tgAM32_DEC( &T_NAME(s_xiFX__Render__Fence__, _Process_Headers_Total) );
    return (KTgS_OK);
}


/* ---- tgFX__Render__, _Render_Generate -------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
static TgVOID T_NAME(tgFX__Render__, _Render_Generate)( PC_STg2_FX_Rnd_Output psRndOut)
{
    TgFX_DATA_INST_ID                   tiActive;
    T_NAME(P_STg2_FX__,)                psEffect;

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

    PROFILE_START( T_TYPE(FX_, _RENDER__GENERATE) );
    PROFILE_START( FX_RENDER_GENERATE );

    tiActive = T_NAME(s_atiFX__, __Render_Generate__Head);
    T_NAME(s_atiFX__, __Render_Generate__Head) = KTgFX_DATA_INST_ID__INVALID;
    while (TgFALSE != tgFX_DATA_INST_ID_Is_Valid( tiActive ))
    {
        psEffect = T_NAME(g_asFX__,) + tiActive.m.iI;

        if (ETgRN_VERTEX_PARTICLE_00 == psEffect->m_enVertex)
        {
            T_NAME(tgFX__Render__, _Render_Generate_Particle_00)( psRndOut, 0, 0 );
        }
        else if (ETgRN_VERTEX_PARTICLE_01 == psEffect->m_enVertex)
        {
            T_NAME(tgFX__Render__, _Render_Generate_Particle_01)( psRndOut, 0, 0 );
        };

        tiActive = psEffect->m_tiNext[ETgFX_NEXT__RENDER];
        psEffect->m_tiNext[ETgFX_NEXT__RENDER] = KTgFX_DATA_INST_ID__INVALID;
    };

    PROFILE_STOP( FX_RENDER_GENERATE );
    PROFILE_STOP( T_TYPE(FX_, _RENDER__GENERATE) );
}


/* ---- tgFX__Render__Job__, _Render_Generate --------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
static TgRESULT T_NAME(tgFX__Render__Job__, _Render_Generate)( PC_STg2_Job psJob )
{
    union
    {
        P_STg2_FX_Job__Render_Generate      psRender_Generate;
        P_TgUINT08                          pui;
    }                                   sUnion;

    sUnion.pui = psJob->m_auiData;

    T_NAME(tgFX__Render__, _Render_Generate)( sUnion.psRender_Generate->m_psRndOut );

    tgAM32_DEC( &g_xiFX_Fence__RENDER_GENERATE );
    return (KTgS_OK);
}


/*# T_EFFECT_RENDER */
#endif