Home

Resume

Blog

Teikitu


/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
/*  »Project«   Teikitu Gaming System (TgS) (∂)
    »File«      TgS Kernel - GPU.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".                                                   */
/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
#if defined(TgCOMPILE_GPU_SUPPORT)

/* == Kernel ============================================================================================================================================================ */

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

static TgKN_GPU_CXT_ID                      tgKN_GPU_Context__Init_Contexts( CPCU_STg2_KN_GPU_Select );
static TgVOID                               tgKN_GPU_Context__Free_Contexts( C_TgKN_GPU_CXT_ID );
/*
static TgRESULT                             tgKN_GPU_Context__Init_Resource( C_TgKN_GPU_CXT_DATA_ID );
static TgRESULT                             tgKN_GPU_Context__Init_External( C_TgKN_GPU_CXT_EXTN_ID );
*/




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

/* ---- tgKN_GPU_Enumerate -------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgKN_GPU_Enumerate( TgVOID )
{
    return (tgKN_GPU_PM_Enumerate());
}


/* ---- tgKN_GPU_Load_Config -------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgKN_GPU_Load_Config( TgVOID )
{
    return (tgKN_GPU_PM_Load_Config());
}


/* ---- tgKN_GPU_Save_Config -------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgKN_GPU_Save_Config( TgVOID )
{
    return (tgKN_GPU_PM_Save_Config());
}


/* ---- tgKN_GPU_Query_Adapter_List ------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgKN_GPU_Query_Adapter_List( PP_TgCHAR ppszAdapter, C_TgSINT32 niAdapter )
{
    TgSINT32                            iAdapter;

    TgPARAM_CHECK( niAdapter >= KTgKN_GPU_MAX_ADAPTER );

    for (iAdapter = 0; iAdapter < g_niKN_GPU_Adapter; ++iAdapter)
    {
        ppszAdapter[iAdapter] = g_asKN_GPU_Adapter[iAdapter].m_szAdapter;
    };

    for (; iAdapter < niAdapter; ++iAdapter)
    {
        ppszAdapter[iAdapter] = nullptr;
    };

    return (KTgS_OK);
}


/* ---- tgKN_GPU_Query_Output_List -------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgKN_GPU_Query_Output_List( C_TgSINT32 iAdapter, PP_TgCHAR ppszOutput, C_TgSINT32 niOutput )
{
    TgSINT32                            iOutput;

    TgPARAM_CHECK_INDEX( iAdapter, g_asKN_GPU_Adapter );
    TgPARAM_CHECK( niOutput >= KTgKN_GPU_MAX_OUTPUT );

    for (iOutput = 0; iOutput < g_asKN_GPU_Adapter[iAdapter].m_niOutput; ++iOutput)
    {
        ppszOutput[iOutput] = g_asKN_GPU_Adapter[iAdapter].m_asOutput[iOutput].m_szName;
    };

    for (; iOutput < niOutput; ++iOutput)
    {
        ppszOutput[iOutput] = nullptr;
    };

    return (KTgS_OK);
}


/* ---- tgKN_GPU_Query_Output_ScanOut_Format_Support -------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgBOOL tgKN_GPU_Query_Output_ScanOut_Format_Support( C_TgSINT32 iAdapter, C_TgSINT32 iOutput, C_ETgKN_GPU_TARGET enFormat )
{
    TgPARAM_CHECK_INDEX( iAdapter, g_asKN_GPU_Adapter );
    TgPARAM_CHECK( iOutput < g_asKN_GPU_Adapter[iAdapter].m_niOutput );

    return (tgBF_Query_Flag_U64( &g_asKN_GPU_Adapter[iAdapter].m_asOutput[iOutput].m_uiFlags, ETgKN_GPU_ADAPTER_OUTPUT_FLAGS__TARGET__START + enFormat ));
}


/* ---- tgKN_GPU_Query_Mode_List ---------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgSINT32 tgKN_GPU_Query_Mode_List( P_STg2_KN_GPU_Mode psMode, C_TgSINT32 niMode, C_TgSINT32 iAdapter, C_TgSINT32 iOutput, C_ETgKN_GPU_TARGET enForamt )
{
    return (tgKN_GPU_PM_Query_Mode_List( psMode, niMode, iAdapter, iOutput, enForamt ));
}


/* ---- tgKN_GPU_Select_Context__Init_From_Config ----------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgKN_GPU_Select_Context__Init_From_Config( P_STg2_KN_GPU_Select UNUSED_PARAM psSelect )
{
    return (KTgS_OK);
}


/* ---- tgKN_GPU_Select_Context__Validate ------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgKN_GPU_Select_Context__Validate( P_STg2_KN_GPU_Select UNUSED_PARAM psSelect )
{
    return (KTgS_OK);
}


/* ---- tgKN_GPU_Select_Context ----------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgKN_GPU_Select_Context( PCU_STg2_KN_GPU_Select UNUSED_PARAM psSelect ) /* #IMPLEMENT */
{
    return (KTgS_OK);
}
/*
    P_STg2_KN_GPU_Adapter_Info          psAdapter;

    for (psAdapter = g_psKN_GPU_Adapter_Info; nullptr != psAdapter; psAdapter = psAdapter->m_psNext)
    {
        TgUINT32                            uiMatch;

        uiMatch = 0;

        tgBF_Set_Flag_U32( &uiMatch, ETGKN_GPU_SELECT_ORDER__ADAPTER, psAdapter->m_iOrdinal == psSelect->m_iAdapter_Ordinal );
        tgBF_Set_Flag_U32( &uiMatch, ETGKN_GPU_SELECT_ORDER__OUTPUT, psAdapter->m_iOrdinal == psSelect->m_iAdapter_Ordinal );

        // Hard Match: Requests for non full screen (window) must match the desktop mode (on a per adapter basis)
        if (TgTRUE == psSelect->m_bWindow)
        {
            sMode = psAdapter->m_sDesktop_Mode;
        }
        else
        {
            sMode.Width = psSelect->m_uiW;
            sMode.Height = psSelect->m_uiH;
            sMode.RefreshRate = psSelect->m_uiRefresh_Rate;
            sMode.Format = KTgKN_DX_FORMAT_LIST[psSelect->m_enFM0];
        }

        // Hard Match: Validate that the mode exists in the mode list (paranoid search for window mode)
        for (iMode = 0; iMode < psAdapter->m_niModes && 0 != memcmp(psAdapter->m_psMode + iMode, &sMode, sizeof(sMode)); ++iMode);
        if (iMode >= psAdapter->m_niModes)
        {
            continue;
        }

        // Hard Match: Select a device instantiation
        TgASSERT(psSelect->m_enInfo >= 0 && psSelect->m_enInfo < ETgKN_GPU_DX__MAX);
        psInfo = psAdapter->m_apsInfo[psSelect->m_enInfo];

        if (nullptr == psInfo)
        {
            continue;
        }

        for (iInst = 0; iInst < psInfo->m_niDevice_Inst; ++iInst)
        {
            psInst = psInfo->m_psDevice_Inst + iInst;

            // Hard Match: Primary, Back and Window Mode must all match the selected values
            if (   KTgKN_DX_FORMAT_LIST[psSelect->m_enFM0] != psInst->m_enFM0
                || KTgKN_DX_FORMAT_LIST[psSelect->m_enFM1] != psInst->m_enFM1
                || psSelect->m_bWindow != tgBF_Query_Flag_U32( &psInst->m_uiFlags, ETgKN_GPU_DEVICE_INST_FLAGS__WINDOW ) )
            {
                continue;
            };

            // Soft Match: Validate the multi sample mode for the depth stencil - find the closest value less than or equal
            for (iMS = psSelect->m_enMS; iMS >= 0; --iMS)
            {
                if (TgTRUE == tgBF_Query_Flag_U32( psInst->m_abDS_MS + psSelect->m_enDS, iMS ))
                {
                    break;
                };
            };

            // Store the results of the selection
            psSelect->m_enMS = KTgKN_DX_MULTISAMPLE_LIST[iMS];
            psSelect->m_iAdapter = iAdapter;
            psSelect->m_iInst = iInst;

            return (KTgS_OK);
        };
    };

    return (KTgE_FAIL);
}
*/


/* ---- tgKN_GPU_Context__Init ------------------------------------------------------------------------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgKN_GPU_CXT_ID tgKN_GPU_Context__Init( CPCU_STg2_KN_GPU_Select psSelect ) /* #IMPLEMENT */
{
    TgKN_GPU_CXT_ID                     tiRet;

    tiRet = tgKN_GPU_Context__Init_Contexts( psSelect );
    if (TgTRUE != tgKN_GPU_CXT_ID_Is_Valid( tiRet ))
    {
        TgERROR_MSGF( 0, TgT("%-16.16s(%-32.32s): %-48.48s\n"), TgT("Kernel"), TgT("tgKN_GPU_Context__Init"), TgT("Failed to Create Context") );
        return (KTgKN_GPU_CXT_ID__INVALID);
    };

    if (TgFAILED(tgKN_GPU_PM_Context__Init( tiRet, psSelect )))
    {
        TgERROR_MSGF( 0, TgT("%-16.16s(%-32.32s): %-48.48s\n"), TgT("Kernel"), TgT("tgKN_GPU_Context__Init"), TgT("Failed to Init Platform Contexts") );
        tgKN_GPU_Context__Free_Contexts( tiRet );
        return (KTgKN_GPU_CXT_ID__INVALID);
    };

    /*
    if (TgFAILED( tgKN_GPU_Context__Init( iCT ) ))
    {
        tgKN_GPU_PM_Render_Context__Free( iCT );
        tgCN_PrintF( KTgCN_CHANEL_ERROR, TgT( "%-16.16s(%-32.32s): %-48.48s\n" ), TgT("Kernel"), TgT("Init Render Context"),
                     TgT("Failed to Create Default Render Resources") );
        return (-1);
    };
    */

    return (tiRet);
}


/* ---- tgKN_GPU_Context__Free ------------------------------------------------------------------------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgVOID tgKN_GPU_Context__Free( C_TgKN_GPU_CXT_ID UNUSED_PARAM tiCXT ) /* #IMPLEMENT */
{
}




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

/* ---- tgKN_GPU_Context__Init_Contexts --------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
static TgKN_GPU_CXT_ID tgKN_GPU_Context__Init_Contexts( CPCU_STg2_KN_GPU_Select psSelect )
{
    union {
        P_STg2_KN_GPU_Context               ps;
        P_STg2_UTM_Node                     pNode;
    }                                   sCXT;
    union {
        P_STg2_KN_GPU_Context__Device       ps;
        P_STg2_UTM_Node                     pNode;
    }                                   sCXT_DEVC;
    union {
        P_STg2_KN_GPU_Context__Output       ps;
        P_STg2_UTM_Node                     pNode;
    }                                   sCXT_SWAP;
    union {
        P_STg2_KN_GPU_Context__Resource     ps;
        P_STg2_UTM_Node                     pNode;
    }                                   sCXT_DATA;
    union {
        P_STg2_KN_GPU_Context__External     ps;
        P_STg2_UTM_Node                     pNode;
    }                                   sCXT_EXTN;

    /* Parent Context structure */
    sCXT.pNode = tgCM_UTM_AM_ST_Pop( &g_sKN_GPU_Context__Free_Stack.m_sStack );
    if (nullptr == sCXT.pNode)
    {
        return (KTgKN_GPU_CXT_ID__INVALID);
    };

    /* Device Context */
    if (TgTRUE != tgKN_GPU_CXT_DEVC_ID_Is_Valid( psSelect->m_tiCXT_DEVC ))
    {
        sCXT_DEVC.pNode = tgCM_UTM_AM_ST_Pop( &g_sKN_GPU_Context_Device__Free_Stack.m_sStack );
        if (nullptr != sCXT_DEVC.pNode)
        {
            memset( sCXT_DEVC.pNode, 0, sizeof( STg2_KN_GPU_Context__Device ) );
        };
    }
    else
    {
        TgERROR_INDEX( psSelect->m_tiCXT_DEVC.m.iI, g_asKN_GPU_Context_Device );
        sCXT_DEVC.ps = g_asKN_GPU_Context_Device + psSelect->m_tiCXT_DEVC.m.iI;
        if (TgTRUE != tgEQ_KN_GPU_CXT_DEVC_ID( psSelect->m_tiCXT_DEVC, sCXT_DEVC.ps->m_tiID ))
        {
            sCXT_DEVC.ps = nullptr;
        };
    };

    if (nullptr == sCXT_DEVC.pNode)
        goto Init_Contexts__Fail_DEVC;


    /* Output Context */
    sCXT_SWAP.pNode = tgCM_UTM_AM_ST_Pop( &g_sKN_GPU_Context_Output__Free_Stack.m_sStack );
    if (nullptr != sCXT_SWAP.pNode)
    {
        memset( sCXT_SWAP.pNode, 0, sizeof( STg2_KN_GPU_Context__Output ) );
    }
    else
    {
        goto Init_Contexts__Fail_SWAP;
    };


    /* Resource Context */
    if (TgTRUE != tgKN_GPU_CXT_DATA_ID_Is_Valid( psSelect->m_tiCXT_DATA ))
    {
        sCXT_DATA.pNode = tgCM_UTM_AM_ST_Pop( &g_sKN_GPU_Context_Resource__Free_Stack.m_sStack );
        if (nullptr != sCXT_DATA.pNode)
        {
            memset( sCXT_DATA.pNode, 0, sizeof( STg2_KN_GPU_Context__Resource ) );
        };
    }
    else
    {
        TgERROR_INDEX( psSelect->m_tiCXT_DATA.m.iI, g_asKN_GPU_Context_Resource );
        sCXT_DATA.ps = g_asKN_GPU_Context_Resource + psSelect->m_tiCXT_DATA.m.iI;
        if (TgTRUE != tgEQ_KN_GPU_CXT_DATA_ID( psSelect->m_tiCXT_DATA, sCXT_DATA.ps->m_tiID ))
        {
            sCXT_DATA.ps = nullptr;
        };
    };

    if (nullptr == sCXT_DATA.pNode)
        goto Init_Contexts__Fail_RESC;


    /* External Context */
    if (TgTRUE != tgKN_GPU_CXT_EXTN_ID_Is_Valid( psSelect->m_tiCXT_EXTN ))
    {
        sCXT_EXTN.pNode = tgCM_UTM_AM_ST_Pop( &g_sKN_GPU_Context_External__Free_Stack.m_sStack );
        if (nullptr != sCXT_EXTN.pNode)
        {
            memset( sCXT_EXTN.pNode, 0, sizeof( STg2_KN_GPU_Context__External ) );
        };
    }
    else
    {
        TgERROR_INDEX( psSelect->m_tiCXT_EXTN.m.iI, g_asKN_GPU_Context_External );
        sCXT_EXTN.ps = g_asKN_GPU_Context_External + psSelect->m_tiCXT_EXTN.m.iI;
        if (TgTRUE != tgEQ_KN_GPU_CXT_EXTN_ID( psSelect->m_tiCXT_EXTN, sCXT_EXTN.ps->m_tiID ))
        {
            sCXT_EXTN.ps = nullptr;
        };
    };

    if (nullptr == sCXT_EXTN.pNode)
        goto Init_Contexts__Fail_EXTN;


    if (TgTRUE != tgKN_GPU_CXT_DEVC_ID_Is_Valid( psSelect->m_tiCXT_DEVC ))
        tgInit_KN_GPU_CXT_DEVC_ID( &sCXT_DEVC.ps->m_tiID, (TgSINT32)(sCXT_DEVC.ps - g_asKN_GPU_Context_Device) );
    if (TgTRUE != tgKN_GPU_CXT_DATA_ID_Is_Valid( psSelect->m_tiCXT_DATA ))
        tgInit_KN_GPU_CXT_DATA_ID( &sCXT_DATA.ps->m_tiID, (TgSINT32)(sCXT_DATA.ps - g_asKN_GPU_Context_Resource) );
    if (TgTRUE != tgKN_GPU_CXT_EXTN_ID_Is_Valid( psSelect->m_tiCXT_EXTN ))
        tgInit_KN_GPU_CXT_EXTN_ID( &sCXT_EXTN.ps->m_tiID, (TgSINT32)(sCXT_EXTN.ps - g_asKN_GPU_Context_External) );

    tgInit_KN_GPU_CXT_SWAP_ID( &sCXT_SWAP.ps->m_tiID, (TgSINT32)(sCXT_SWAP.ps - g_asKN_GPU_Context_Output) );
    tgInit_KN_GPU_CXT_ID( &sCXT.ps->m_tiID, (TgSINT32)(sCXT.ps - g_asKN_GPU_Context) );

    sCXT.ps->m_tiCXT_DEVC = sCXT_DEVC.ps->m_tiID;
    ++sCXT_DEVC.ps->m_iRef;
    sCXT.ps->m_tiCXT_DATA = sCXT_DATA.ps->m_tiID;
    ++sCXT_DATA.ps->m_iRef;
    sCXT.ps->m_tiCXT_EXTN = sCXT_EXTN.ps->m_tiID;
    ++sCXT_EXTN.ps->m_iRef;

    return (sCXT.ps->m_tiID);

Init_Contexts__Fail_EXTN:
    if (TgTRUE != tgKN_GPU_CXT_DATA_ID_Is_Valid( psSelect->m_tiCXT_DATA ))
        tgCM_UTM_AM_ST_Push( &g_sKN_GPU_Context_Resource__Free_Stack.m_sStack, sCXT_DATA.pNode );
Init_Contexts__Fail_RESC:
Init_Contexts__Fail_SWAP:
    if (TgTRUE != tgKN_GPU_CXT_DEVC_ID_Is_Valid( psSelect->m_tiCXT_DEVC ))
        tgCM_UTM_AM_ST_Push( &g_sKN_GPU_Context_Device__Free_Stack.m_sStack, sCXT_DEVC.pNode );
Init_Contexts__Fail_DEVC:
    return (KTgKN_GPU_CXT_ID__INVALID);
}


/* ---- tgKN_GPU_Context__Free_Contexts --------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
static TgVOID tgKN_GPU_Context__Free_Contexts( C_TgKN_GPU_CXT_ID tiCXT )
{
    P_STg2_KN_GPU_Context               psCXT;

    union
    {
        P_STg2_KN_GPU_Context               ps;
        P_STg2_UTM_Node                     pNode;
    }                                   sCXT;
    union
    {
        P_STg2_KN_GPU_Context__Device       ps;
        P_STg2_UTM_Node                     pNode;
    }                                   sCXT_DEVC;
    union
    {
        P_STg2_KN_GPU_Context__Output       ps;
        P_STg2_UTM_Node                     pNode;
    }                                   sCXT_SWAP;
    union
    {
        P_STg2_KN_GPU_Context__Resource     ps;
        P_STg2_UTM_Node                     pNode;
    }                                   sCXT_DATA;
    union
    {
        P_STg2_KN_GPU_Context__External     ps;
        P_STg2_UTM_Node                     pNode;
    }                                   sCXT_EXTN;

    psCXT = g_asKN_GPU_Context + tiCXT.m.iI;

    sCXT_EXTN.ps = g_asKN_GPU_Context_External + psCXT->m_tiCXT_EXTN.m.iI;
    sCXT_DATA.ps = g_asKN_GPU_Context_Resource + psCXT->m_tiCXT_DATA.m.iI;
    sCXT_SWAP.ps = g_asKN_GPU_Context_Output + psCXT->m_tiCXT_SWAP.m.iI;
    sCXT_DEVC.ps = g_asKN_GPU_Context_Device + psCXT->m_tiCXT_DEVC.m.iI;
    sCXT.ps = g_asKN_GPU_Context + tiCXT.m.iI;

    --sCXT_DEVC.ps->m_iRef;
    --sCXT_DATA.ps->m_iRef;
    --sCXT_EXTN.ps->m_iRef;

    if (0 >= sCXT_EXTN.ps->m_iRef)
    {
        tgCM_UTM_AM_ST_Push( &g_sKN_GPU_Context_External__Free_Stack.m_sStack, sCXT_EXTN.pNode );
    };

    if (0 >= sCXT_DATA.ps->m_iRef)
    {
        tgCM_UTM_AM_ST_Push( &g_sKN_GPU_Context_Resource__Free_Stack.m_sStack, sCXT_DATA.pNode );
    };

    tgCM_UTM_AM_ST_Push( &g_sKN_GPU_Context_Output__Free_Stack.m_sStack, sCXT_SWAP.pNode );

    if (0 >= sCXT_DEVC.ps->m_iRef)
    {
        tgCM_UTM_AM_ST_Push( &g_sKN_GPU_Context_Device__Free_Stack.m_sStack, sCXT_DEVC.pNode );
    };

    tgCM_UTM_AM_ST_Push( &g_sKN_GPU_Context__Free_Stack.m_sStack, sCXT.pNode );
}


/*# defined(TgCOMPILE_GPU_SUPPORT) */
#endif