Home

Resume

Blog

Teikitu


/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
/*  »Project«   Teikitu Gaming System (TgS) (∂)
    »File«      TgS Kernel - Resource [GPU] [Base].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 ============================================================================================================================================================ */

#include "TgS Kernel - Internal.inl"


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

#if !defined(TgS_FINAL)
static TgKN_GPU_RS_ID                       tgKN_GPU_RS__File_Load_BIN_NoLock(
                                                C_TgKN_FS_MOUNT_ID, CPC_TgCHAR, CPC_TgCHAR, C_ETgKN_GPU_ALLOCATOR, PCU_STg2_KN_GPU_RS_LIB_DESC );
#endif

static TgKN_GPU_RS_ID                       tgKN_GPU_RS__Load_BIN_NoLock( C_TgKN_FILE_ID, C_TgSIZE, C_ETgKN_GPU_ALLOCATOR, PCU_STg2_KN_GPU_RS_LIB_DESC, TgUINTXX );

TgFORCEINLINE TgKN_GPU_RSI_ID               tgKN_GPU_RSI__Find_And_IncRef_NoLock( CPCU_STg2_KN_GPU_RSI_LIB_DESC, C_TgKN_GPU_RS_ID );
TgFORCEINLINE TgVOID                        tgKN_GPU_RS_ID__Check_NoLock( CPCU_STg2_KN_GPU_RS_LIB_DESC, C_TgKN_GPU_RS_ID );
TgFORCEINLINE TgVOID                        tgKN_GPU_RSI_ID__Check_NoLock( CPCU_STg2_KN_GPU_RS_LIB_DESC, CPCU_STg2_KN_GPU_RSI_LIB_DESC, C_TgKN_GPU_RSI_ID );




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

/* ---- tgKN_GPU_RS__File_Load_BIN -------------------------------------------------------------------------------------------------------------------------------------- */
/* REQ: No thread / ownership contention for the library permitted                                                                                                        */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
#if !defined(TgS_FINAL)
TgKN_GPU_RS_ID tgKN_GPU_RS__File_Load_BIN(
    C_TgKN_FS_MOUNT_ID tiFS_Mount, CPC_TgCHAR pszPath, CPC_TgCHAR pszFile, C_ETgKN_GPU_ALLOCATOR enAllocator, PCU_STg2_KN_GPU_RS_LIB_DESC psLIB )
{
    TgKN_GPU_RS_ID                      tiRS;

    TgERROR_MSG( (nullptr != pszFile) && (pszFile[0] != 0), TgT("tgKN_GPU_RS_File_Load_BIN: Invalid File") );
    tgKN_GPU_RS_LIB_DESC_Check( psLIB );

    /* 1. Acquire the library lock - this is a validation step to make sure there is no ownership / thread contention.  This eliminates the race condition where two or */
    /* more threads would attempt to load (or unload) the same resource. */
    if (TgFAILED( tgCM_UTM_SN_Lock_Test( psLIB->m_psLock ) ))
    {
        tgCN_PrintF( KTgCN_CHANEL_ERROR, TgT( "%-16.16s(%-32.32s): [Fail] %-57.57s\n" ), TgT("Kernel"), TgT("tgKN_GPU_RS_File_Load_BIN"),
                     TgT("No thread contention allowed for ownership of the library.") );
        tgCM_UTM_SN_Lock_Spin( psLIB->m_psLock );
    };
    tgAM_READ_FENCE();

    /* 2. Execute the NoLock Internal Function */
    tiRS = tgKN_GPU_RS__File_Load_BIN_NoLock( tiFS_Mount, pszPath, pszFile, enAllocator, psLIB );

    /* 3. Free the lock and return the result */
    tgAM_WRITE_FENCE();
    tgCM_UTM_SN_Signal( psLIB->m_psLock );
    return (tiRS);
}

/*# !defined(TgS_FINAL) */
#endif


/* ---- tgKN_GPU_RS__Load_BIN ------------------------------------------------------------------------------------------------------------------------------------------- */
/* REQ: No thread / ownership contention for the library permitted                                                                                                        */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgKN_GPU_RS_ID tgKN_GPU_RS__Load_BIN(
    C_TgKN_FILE_ID tiFile, C_TgSIZE uiFile_Offset, C_ETgKN_GPU_ALLOCATOR enAllocator, C_TgUINTXX uiHash_RS, PCU_STg2_KN_GPU_RS_LIB_DESC psLIB )
{
    TgKN_GPU_RS_ID                      tiRS;

    TgERROR_MSG( !((TgTRUE == tgKN_FILE_ID_Is_Valid( tiFile )) ^ (uiHash_RS != KTgEMPTY_HASH)), TgT( "tgKN_GPU_RS_Load_BIN: Invalid File and Resource Hash" ) );
    tgKN_GPU_RS_LIB_DESC_Check( psLIB );

    /* 1. Acquire the library lock - this is a validation step to make sure there is no ownership / thread contention.  This eliminates the race condition where two or */
    /* more threads would attempt to load (or unload) the same resource. */
    if (TgFAILED( tgCM_UTM_SN_Lock_Test( psLIB->m_psLock ) ))
    {
        tgCN_PrintF( KTgCN_CHANEL_ERROR, TgT( "%-16.16s(%-32.32s): [Fail] %-57.57s\n" ), TgT("Kernel"), TgT("tgKN_GPU_RS_Load_BIN"),
                     TgT("No thread contention allowed for ownership of the library.") );
        tgCM_UTM_SN_Lock_Spin( psLIB->m_psLock );
    };
    tgAM_READ_FENCE();

    /* 2. Execute the NoLock Internal Function */
    tiRS = tgKN_GPU_RS__Load_BIN_NoLock( tiFile, uiFile_Offset, enAllocator, psLIB, uiHash_RS );

    /* 3. Free the lock and return the result */
    tgAM_WRITE_FENCE();
    tgCM_UTM_SN_Signal( psLIB->m_psLock );
    return (tiRS);
}


/* ---- tgKN_GPU_RS__Release -------------------------------------------------------------------------------------------------------------------------------------------- */
/* REQ: No thread / ownership contention for the library permitted                                                                                                        */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgSINT32 tgKN_GPU_RS__Release( C_TgKN_GPU_RS_ID tiRS, PCU_STg2_KN_GPU_RS_LIB_DESC psLIB )
{
    C_TgSINT32                          iIndex = tiRS.m.iI;
    TgSINT32                            iRef;
    union
    {
        P_TgUINT08                          pui08;
        P_STg2_UTM_Node                     psNode;
    }                                   sLibData;

    tgKN_GPU_RS_LIB_DESC_Check( psLIB );

    iRef = tgAM32_DEC( &psLIB->m_piRef[iIndex] );

    if (0 != iRef)
    {
        return (iRef);
    };

    /* 1. Acquire the library lock - this is a validation step to make sure there is no ownership / thread contention.  This eliminates the race condition where two or */
    /* more threads would attempt to load (or unload) the same resource. */
    if (TgFAILED( tgCM_UTM_SN_Lock_Test( psLIB->m_psLock ) ))
    {
        tgCN_PrintF( KTgCN_CHANEL_ERROR, TgT( "%-16.16s(%-32.32s): [Fail] %-57.57s\n" ), TgT("Kernel"), TgT("tgKN_GPU_RS_Release"),
                     TgT("No thread contention allowed for ownership of the library.") );
        tgCM_UTM_SN_Lock_Spin( psLIB->m_psLock );
    };
    tgAM_READ_FENCE();

    TgERROR( TgFALSE != tgEQ_KN_GPU_RS_ID( tiRS, psLIB->m_ptiRS[iIndex] ) );

    /* 2. Execute the NoLock Internal Function */
    psLIB->m_pfnFree( psLIB, (TgSIZE)iIndex );
    psLIB->m_ptiRS[iIndex] = KTgKN_GPU_RS_ID__INVALID;

    /* 3. Free the lock and return the result */
    tgAM_WRITE_FENCE();
    tgCM_UTM_SN_Signal( psLIB->m_psLock );

    /* 4. Return the resource index to the free pool */
    sLibData.pui08 = psLIB->m_puiData + (TgSIZE)iIndex*psLIB->m_uiStride;
    tgCM_UTM_AM_ST_Push( psLIB->m_psList, sLibData.psNode );

    return (iRef);
}


/* ---- tgKN_GPU_RSI__Init ---------------------------------------------------------------------------------------------------------------------------------------------- */
/* REQ: No thread / ownership contention for the library permitted                                                                                                        */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgKN_GPU_RSI_ID tgKN_GPU_RSI__Init( PCU_STg2_KN_GPU_RSI_LIB_DESC psLibRSI, C_TgUINT32 uiUID, C_TgKN_GPU_RS_ID tiRS )
{
    P_TgUINT08                          puiData;
    TgSINT32                            iRSI;
    TgKN_GPU_RSI_ID                     tiRSI;
    union
    {
        P_TgUINT08                          pui08;
        P_STg2_UTM_Node                     psNode;
    }                                   sLibData;

    TgPARAM_CHECK( TgTRUE == tgKN_GPU_RS_ID_Is_Valid( tiRS ) );
    TgPARAM_CHECK( uiUID <= 0xFFFF );
    tgKN_GPU_RSI_LIB_DESC_Check( psLibRSI );

    /* 1. Acquire the library lock - this is a validation step to make sure there is no ownership / thread contention.  This eliminates the race condition where two or */
    /* more threads would attempt to load (or unload) the same resource. */
    if (TgFAILED( tgCM_UTM_SN_Lock_Test( psLibRSI->m_psLock ) ))
    {
        tgCN_PrintF( KTgCN_CHANEL_ERROR, TgT( "%-16.16s(%-32.32s): [Fail] %-57.57s\n" ), TgT("Kernel"), TgT("tgKN_GPU_RSI_Init"),
                     TgT("No thread contention allowed for ownership of the library.") );
        tgCM_UTM_SN_Lock_Spin( psLibRSI->m_psLock );
    };
    tgAM_READ_FENCE();

    /* 2. Look for the resource in the existing allocation list - setting the max count to zero forces the step to be skipped */
    tiRSI = tgKN_GPU_RSI__Find_And_IncRef_NoLock( psLibRSI, tiRS );
    if (TgTRUE == tgKN_GPU_RSI_ID_Is_Valid( tiRSI ))
    {
        tgAM_WRITE_FENCE();
        tgCM_UTM_SN_Signal( psLibRSI->m_psLock );
        return (tiRSI);
    };

    /* 3. Allocate a new resource from the free list of the library */
    puiData = (P_TgUINT08)tgCM_UTM_AM_ST_Pop( psLibRSI->m_psList );
    if (nullptr == puiData)
    {
        tgCN_PrintF( KTgCN_CHANEL_WARNING, TgT( "%-16.16s(%-32.32s): [Warn] %-57.57s\n" ), TgT("Kernel"), TgT("tgKN_GPU_RSI_Init"),
                     TgT("Failed to allocate a resource entry") );
        tgCM_UTM_SN_Signal( psLibRSI->m_psLock );
        return (KTgKN_GPU_RSI_ID__INVALID);
    };
    iRSI = (TgSINT32)((TgSIZE)(puiData - psLibRSI->m_puiData) / psLibRSI->m_uiStride);

    /* 4. Initialize the instance structure in the context, and execute the instance init function */
    tgInit_KN_GPU_RSI_ID( &tiRSI, iRSI );
    tiRSI.m.iK &= 0xFFFF;
    tiRSI.m.iK |= uiUID << 16;

    psLibRSI->m_ptiRSI[iRSI] = tiRSI;
    psLibRSI->m_piRef[iRSI] = 1;
    psLibRSI->m_ptiRS[iRSI] = tiRS;

    psLibRSI->m_pfnInst( psLibRSI, tiRSI );

    /* 5. Check for failure, and return the id to the usage pool before returning with an error state. */
    if (TgTRUE != tgKN_GPU_RSI_ID_Is_Valid( psLibRSI->m_ptiRSI[iRSI] ))
    {
        psLibRSI->m_piRef[iRSI] = 0;
        psLibRSI->m_ptiRS[iRSI] = KTgKN_GPU_RS_ID__INVALID;

        sLibData.pui08 = psLibRSI->m_puiData + (TgSIZE)iRSI*psLibRSI->m_uiStride;
        tgCM_UTM_AM_ST_Push( psLibRSI->m_psList, sLibData.psNode );
        tgCM_UTM_SN_Signal( psLibRSI->m_psLock );
        return (KTgKN_GPU_RSI_ID__INVALID);
    };

    /* 6. Free the lock and return the result */
    tgAM_WRITE_FENCE();
    tgCM_UTM_SN_Signal( psLibRSI->m_psLock );

    return (tiRSI);
}


/* ---- tgKN_GPU_RSI__IncRef -------------------------------------------------------------------------------------------------------------------------------------------- */
/* REQ: No thread / ownership contention for the library permitted.                                                                                                       */
/* REQ: The instance parameter needs to be valid.                                                                                                                         */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgKN_GPU_RSI_ID tgKN_GPU_RSI__IncRef( CPCU_STg2_KN_GPU_RSI_LIB_DESC psLibRSI, C_TgKN_GPU_RSI_ID tiRSI )
{
    TgPARAM_CHECK( TgTRUE == tgKN_GPU_RSI_ID_Is_Valid( tiRSI ) );
    tgKN_GPU_RSI_LIB_DESC_Check( psLibRSI );

    /* 1. Acquire the library lock - this is a validation step to make sure there is no ownership / thread contention.  This eliminates the race condition where two or */
    /* more threads would attempt to load (or unload) the same resource. */
    if (TgFAILED( tgCM_UTM_SN_Lock_Test( psLibRSI->m_psLock ) ))
    {
        tgCN_PrintF( KTgCN_CHANEL_ERROR, TgT( "%-16.16s(%-32.32s): [Fail] %-57.57s\n" ), TgT("Kernel"), TgT("tgKN_GPU_RSI_IncRef"),
                     TgT("No thread contention allowed for ownership of the library.") );
        tgCM_UTM_SN_Lock_Spin( psLibRSI->m_psLock );
    };
    tgAM_READ_FENCE();

    /* 2. Increment the reference count and return the instance parameter as valid */
    tgKN_GPU_RSI_ID__Check_NoLock( psLibRSI->m_pLibRS, psLibRSI, tiRSI );
    ++psLibRSI->m_piRef[tiRSI.m.iI];

    /* 3. Free the lock and return the result */
    tgAM_WRITE_FENCE();
    tgCM_UTM_SN_Signal( psLibRSI->m_psLock );
    return (tiRSI);
}


/* ---- tgKN_GPU_RSI__Hash_Find_And_IncRef ------------------------------------------------------------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgKN_GPU_RSI_ID tgKN_GPU_RSI__Hash_Find_And_IncRef( PCU_STg2_KN_GPU_RSI_LIB_DESC psLibRSI, C_TgUINT32 uiUID, C_TgUINTXX uiHash )
{
    TgKN_GPU_RSI_ID                     tiRSI;
    TgSINT32                            iIndex;

    tgKN_GPU_RSI_LIB_DESC_Check( psLibRSI );

    /* 1. Acquire the library lock - this is a validation step to make sure there is no ownership / thread contention.  This eliminates the race condition where two or */
    /* more threads would attempt to load (or unload) the same resource. */
    if (TgFAILED( tgCM_UTM_SN_Lock_Test( psLibRSI->m_pLibRS->m_psLock ) ))
    {
        tgCN_PrintF( KTgCN_CHANEL_ERROR, TgT( "%-16.16s(%-32.32s): [Fail] %-57.57s\n" ), TgT("Kernel"), TgT("tgKN_GPU_RSI_Hash_Init"),
                     TgT("No thread contention allowed for ownership of the library.") );
        tgCM_UTM_SN_Lock_Spin( psLibRSI->m_pLibRS->m_psLock );
    };
    tgAM_READ_FENCE();

    /* 2. Look for the resource in the existing allocation list - setting the max count to zero forces the step to be skipped */
    for (iIndex = 0; iIndex < psLibRSI->m_pLibRS->m_iMaxList; ++iIndex)
    {
        if (psLibRSI->m_pLibRS->m_puiHash[iIndex] == uiHash)
        {
            tiRSI = tgKN_GPU_RSI__Init( psLibRSI, uiUID, psLibRSI->m_pLibRS->m_ptiRS[iIndex] );
            tgAM_WRITE_FENCE();
            tgCM_UTM_SN_Signal( psLibRSI->m_pLibRS->m_psLock );
            return (tiRSI);
        };
    };

    /* 3. Unable to find the hash in the resource library */
    tgAM_WRITE_FENCE();
    tgCM_UTM_SN_Signal( psLibRSI->m_pLibRS->m_psLock );

    return (KTgKN_GPU_RSI_ID__INVALID);
}


/* ---- tgKN_GPU_RSI__Release ------------------------------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgSINT32 tgKN_GPU_RSI__Release( PCU_STg2_KN_GPU_RSI_LIB_DESC psLibRSI, C_TgKN_GPU_RSI_ID tiRSI )
{
    C_TgSINT32                          iIndex = tiRSI.m.iI;
    TgSINT32                            iRef;
    union
    {
        P_TgUINT08                          pui08;
        P_STg2_UTM_Node                     psNode;
    }                                   sLibData;

    tgKN_GPU_RSI_LIB_DESC_Check( psLibRSI );
    tgKN_GPU_RSI_ID__Check_NoLock( 0, psLibRSI, tiRSI );

    iRef = tgAM32_DEC( &psLibRSI->m_piRef[iIndex] );

    if (0 != iRef)
    {
        return (iRef);
    };

    /* 1. Acquire the library lock - this is a validation step to make sure there is no ownership / thread contention.  This eliminates the race condition where two or */
    /* more threads would attempt to load (or unload) the same resource. */
    if (TgFAILED( tgCM_UTM_SN_Lock_Test( psLibRSI->m_psLock ) ))
    {
        tgCN_PrintF( KTgCN_CHANEL_ERROR, TgT( "%-16.16s(%-32.32s): [Fail] %-57.57s\n" ), TgT("Kernel"), TgT("tgKN_GPU_RSI_Release"),
                     TgT("No thread contention allowed for ownership of the library.") );
        tgCM_UTM_SN_Lock_Spin( psLibRSI->m_psLock );
    };
    tgAM_READ_FENCE();

    /* 2. Execute the NoLock Internal Function */
    psLibRSI->m_pfnFree( psLibRSI, tiRSI );
    psLibRSI->m_ptiRSI[iIndex] = KTgKN_GPU_RSI_ID__INVALID;

    /* 3. Free the lock and return the result */
    tgAM_WRITE_FENCE();
    tgCM_UTM_SN_Signal( psLibRSI->m_psLock );

    /* 4. Return the resource index to the free pool */
    sLibData.pui08 = psLibRSI->m_puiData + (TgSIZE)iIndex*psLibRSI->m_uiStride;
    tgCM_UTM_AM_ST_Push( psLibRSI->m_psList, sLibData.psNode );

    return (iRef);
}




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

/* ---- tgKN_GPU_RS__File_Load_BIN_NoLock ------------------------------------------------------------------------------------------------------------------------------- */
/* #FIX: See next function                                                                                                                                                */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
#if !defined(TgS_FINAL)
static TgKN_GPU_RS_ID tgKN_GPU_RS__File_Load_BIN_NoLock(
    C_TgKN_FS_MOUNT_ID tiFS_Mount, CPC_TgCHAR UNUSED_PARAM pszPath, CPC_TgCHAR pszFile, C_ETgKN_GPU_ALLOCATOR enAllocator, PCU_STg2_KN_GPU_RS_LIB_DESC psLIB )
{
    STg2_KN_File_Open_Command           sOpen_Cmd;
    TgKN_FILE_ID                        tiFile;
    TgUINTXX                            uiFile;
    TgUINTXX                            uiPath;
    TgSIZE                              uiIndex;
    TgKN_GPU_RS_ID                      tiRS;
    P_TgUINT08                          puiData;
    union
    {
        P_TgUINT08                          pui08;
        P_STg2_UTM_Node                     psNode;
    }                                   sLibData;

    /* 1. Look for the resource in the existing allocation list - setting the max count to zero forces the step to be skipped */
    uiFile = tgSZ_Hash_File_Name( pszFile );
    for (uiIndex = 0; uiIndex < psLIB->m_nuiMax_Hash; ++uiIndex)
    {
        if (psLIB->m_puiHash[uiIndex] == uiFile)
        {
            TgERROR( TgTRUE == tgKN_GPU_RS_ID_Is_Valid( psLIB->m_ptiRS[uiIndex] ) );
            ++psLIB->m_piRef[uiIndex];
            return (psLIB->m_ptiRS[uiIndex]);
        };
    };

    /* 2. Allocate a new resource from the free list of the library */
    puiData = (P_TgUINT08)tgCM_UTM_AM_ST_Pop( psLIB->m_psList );
    if (nullptr == puiData)
    {
        tgCN_PrintF( KTgCN_CHANEL_WARNING, TgT( "%-16.16s(%-32.32s): [Warn] %-57.57s\n" ), TgT("Kernel"), TgT("tgKN_GPU_RS_File_Load_BIN_NoLock"),
                     TgT("Failed to allocate a resource entry") );
        return (KTgKN_GPU_RS_ID__INVALID);
    };
    uiIndex = (TgSIZE)(puiData - psLIB->m_puiData) / psLIB->m_uiStride;

    tgInit_KN_GPU_RS_ID( &tiRS, (TgSINT32)uiIndex );
    psLIB->m_ptiRS[uiIndex] = tiRS;

    /* 3. Open the file for a blocking load.  Non-Blocking loads should not be done through the file execution path */
    uiPath = tgSZ_Hash_Directory( pszFile );

    sOpen_Cmd.m_tiFS_Mount = tiFS_Mount;
    sOpen_Cmd.m_uiPath = uiPath;
    sOpen_Cmd.m_uiFile = uiFile;
    sOpen_Cmd.m_enMode = ETgFILE_IO_ACCESS__READ | ETgFILE_IO_ACCESS__SHARED;
    sOpen_Cmd.m_iCache = 0;
    sOpen_Cmd.m_pszFile_Name = nullptr;

    tiFile = tgKN_FS_BL_Open( &sOpen_Cmd );

    if (TgTRUE != tgKN_FILE_ID_Is_Valid( tiFile ))
    {
        sLibData.pui08 = psLIB->m_puiData + uiIndex*psLIB->m_uiStride;
        tgCM_UTM_AM_ST_Push( psLIB->m_psList, sLibData.psNode );
        return (KTgKN_GPU_RS_ID__INVALID);
    };

    /* 4. Load the resource from the file input */
    psLIB->m_pfnLoad( tiFile, 0, enAllocator, psLIB, uiFile, uiIndex );

    tgKN_FS_BL_Close( tiFile );

    /* 5. Success: assign the hash into the key list, Fail: return the resource id back to the free list */
    if (TgTRUE == tgKN_GPU_RS_ID_Is_Valid( psLIB->m_ptiRS[uiIndex] ))
    {
        TgERROR( 0 < psLIB->m_piRef[uiIndex] );
        psLIB->m_puiHash[uiIndex] = uiFile;
        return (tiRS);
    }
    else
    {
        psLIB->m_ptiRS[uiIndex] = KTgKN_GPU_RS_ID__INVALID;
        sLibData.pui08 = psLIB->m_puiData + uiIndex*psLIB->m_uiStride;
        tgCM_UTM_AM_ST_Push( psLIB->m_psList, sLibData.psNode );
        return (KTgKN_GPU_RS_ID__INVALID);
    };
}

/*# !defined(TgS_FINAL) */
#endif


/* ---- tgKN_GPU_RS__Load_BIN_NoLock ------------------------------------------------------------------------------------------------------------------------------------ */
/* #PERF: Search for existing library entry that has a matching hash value - unordered set                                                                                */
/* #FEATURE: Need to be able to load on a MIP by MIP basis                                                                                                                */
/* #FEATURE: Change load to return the Hash RS prior to executing a load                                                                                                  */
/* #FEATURE: Loading needs to take into account that it will be executed asynchronously                                                                                   */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
static TgKN_GPU_RS_ID tgKN_GPU_RS__Load_BIN_NoLock(
    C_TgKN_FILE_ID tiFile, C_TgSIZE uiFile_Offset, C_ETgKN_GPU_ALLOCATOR enAllocator, PCU_STg2_KN_GPU_RS_LIB_DESC psLIB, TgUINTXX uiHash_RS )
{
    P_TgUINT08                          puiData;
    TgSIZE                              uiIndex;
    TgKN_GPU_RS_ID                      tiRS;
    TgBOOL                              bNoFile;
    union
    {
        P_TgUINT08                          pui08;
        P_STg2_UTM_Node                     psNode;
    }                                   sLibData;

    bNoFile = KTgEMPTY_HASH == uiHash_RS;

    /* 1. Look for the resource in the existing allocation list - setting the max count to zero forces the step to be skipped */
    if (!bNoFile)
    {
        for (uiIndex = 0; uiIndex < psLIB->m_nuiMax_Hash; ++uiIndex)
        {
            if (psLIB->m_puiHash[uiIndex] == uiHash_RS)
            {
                TgERROR( TgTRUE == tgKN_GPU_RS_ID_Is_Valid( psLIB->m_ptiRS[uiIndex] ) );
                ++psLIB->m_piRef[uiIndex];
                return (psLIB->m_ptiRS[uiIndex]);
            };
        };
    };

    /* 2. Allocate a new resource from the free list of the library */
    puiData = (P_TgUINT08)tgCM_UTM_AM_ST_Pop( psLIB->m_psList );
    if (nullptr == puiData)
    {
        tgCN_PrintF( KTgCN_CHANEL_WARNING, TgT( "%-16.16s(%-32.32s): [Warn] %-57.57s\n" ), TgT("Kernel"), TgT("tgKN_GPU_RS_Load_BIN_NoLock"),
                     TgT("Failed to allocate a resource entry") );
        return (KTgKN_GPU_RS_ID__INVALID);
    };
    uiIndex = (TgSIZE)(puiData - psLIB->m_puiData) / psLIB->m_uiStride;

    tgInit_KN_GPU_RS_ID( &tiRS, (TgSINT32)uiIndex );
    psLIB->m_ptiRS[uiIndex] = tiRS;

    /* 3. Load the resource from the file input */
    uiHash_RS = psLIB->m_pfnLoad( tiFile, uiFile_Offset, enAllocator, psLIB, uiHash_RS, uiIndex );

    /* 4. Success: assign the hash into the key list, Fail: return the resource id back to the free list */
    if (TgTRUE == tgKN_GPU_RS_ID_Is_Valid( psLIB->m_ptiRS[uiIndex] ))
    {
        TgERROR( 0 < psLIB->m_piRef[uiIndex] );
        TgERROR( KTgEMPTY_HASH != uiHash_RS );

        if (bNoFile)
        {
            for (uiIndex = 0; uiIndex < psLIB->m_nuiMax_Hash; ++uiIndex)
            {
                if (psLIB->m_puiHash[uiIndex] == uiHash_RS)
                {
                    tgCN_PrintF( KTgCN_CHANEL_ERROR, TgT( "%-16.16s(%-32.32s): [Fail] %-57.57s\n" ), TgT("Kernel"), TgT("tgKN_GPU_RS_Load_BIN_NoLock"),
                                 TgT("Hash collision on a hashless resource load") );
                    psLIB->m_pfnFree( psLIB, uiIndex );
                    psLIB->m_ptiRS[uiIndex] = KTgKN_GPU_RS_ID__INVALID;
                    sLibData.pui08 = psLIB->m_puiData + uiIndex*psLIB->m_uiStride;
                    tgCM_UTM_AM_ST_Push( psLIB->m_psList, sLibData.psNode );
                    return (KTgKN_GPU_RS_ID__INVALID);
                };
            };
        };

        psLIB->m_puiHash[uiIndex] = uiHash_RS;
        return (tiRS);
    }
    else
    {
        psLIB->m_ptiRS[uiIndex] = KTgKN_GPU_RS_ID__INVALID;
        sLibData.pui08 = psLIB->m_puiData + uiIndex*psLIB->m_uiStride;
        tgCM_UTM_AM_ST_Push( psLIB->m_psList, sLibData.psNode );
        return (KTgKN_GPU_RS_ID__INVALID);
    };
}


/* ---- tgKN_GPU_RSI__Find_And_IncRef_NoLock ---------------------------------------------------------------------------------------------------------------------------- */
/* #PERF: Looking for a RSI that has already instanced the RS - linked list attached to the RS?                                                                           */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgFORCEINLINE TgKN_GPU_RSI_ID tgKN_GPU_RSI__Find_And_IncRef_NoLock( CPCU_STg2_KN_GPU_RSI_LIB_DESC psLibRSI, C_TgKN_GPU_RS_ID tiRS )
{
    TgSINT32                            iRSI;

    TgPARAM_CHECK( nullptr != psLibRSI && nullptr != psLibRSI->m_pLibRS );

    for (iRSI = 0; iRSI < psLibRSI->m_iMaxList; ++iRSI)
    {
        if (TgFALSE != tgEQ_KN_GPU_RS_ID( tiRS, psLibRSI->m_ptiRS[iRSI] ))
        {
            tgKN_GPU_RSI_ID__Check_NoLock( psLibRSI->m_pLibRS, psLibRSI, psLibRSI->m_ptiRSI[iRSI] );
            ++psLibRSI->m_piRef[iRSI];
            return (psLibRSI->m_ptiRSI[iRSI]);
        };
    };

    return (KTgKN_GPU_RSI_ID__INVALID);
}


/* ---- tgKN_GPU_RS_ID__Check_NoLock ------------------------------------------------------------------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgFORCEINLINE TgVOID tgKN_GPU_RS_ID__Check_NoLock( CPCU_STg2_KN_GPU_RS_LIB_DESC psLIB, C_TgKN_GPU_RS_ID tiRS )
{
    TgERROR( nullptr != psLIB );
    TgERROR( tiRS.m.iI >= 0 && tiRS.m.iI < psLIB->m_iMaxList );
    TgERROR( TgTRUE == tgKN_GPU_RS_ID_Is_Valid( tiRS ) );
    TgERROR( TgTRUE == tgEQ_KN_GPU_RS_ID( tiRS, psLIB->m_ptiRS[tiRS.m.iI] ) );
}


/* ---- tgKN_GPU_RSI_ID__Check_NoLock ------------------------------------------------------------------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgFORCEINLINE TgVOID tgKN_GPU_RSI_ID__Check_NoLock( CPCU_STg2_KN_GPU_RS_LIB_DESC psLIB, CPCU_STg2_KN_GPU_RSI_LIB_DESC psLibRSI, C_TgKN_GPU_RSI_ID tiRSI )
{
    TgERROR( nullptr != psLibRSI );
    TgERROR( tiRSI.m.iI >= 0 && tiRSI.m.iI < psLibRSI->m_iMaxList );
    TgERROR( TgTRUE == tgKN_GPU_RSI_ID_Is_Valid( tiRSI ) );
    TgERROR( TgTRUE == tgEQ_KN_GPU_RSI_ID( tiRSI, psLibRSI->m_ptiRSI[tiRSI.m.iI] ) );
    if (0 != psLIB)
    {
        tgKN_GPU_RS_ID__Check_NoLock( psLIB, psLibRSI->m_ptiRS[tiRSI.m.iI] );
    };
}

/*# defined(TgCOMPILE_GPU_SUPPORT) */
#endif