Home

Resume

Blog

Teikitu


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

#include "TgS (DX12) Kernel - Internal - D3DX.inl"


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

/* Constant buffer used to send MVP matrices to the vertex shader. */
typedef struct ModelViewProjectionConstantBuffer
{
    TgMAT_F32_44 model;
    TgMAT_F32_44 view;
    TgMAT_F32_44 projection;
} ModelViewProjectionConstantBuffer;

/* Used to send per-vertex data to the vertex shader. */
typedef struct VertexPositionColor
{
    float pos[3];
    float color[3];
} VertexPositionColor;


/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */
/*  Public Functions                                                                                                                                                      */
/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */
static D3D12_VERTEX_BUFFER_VIEW s_vertexBufferView;
static D3D12_INDEX_BUFFER_VIEW s_indexBufferView;
static ID3D12RootSignature *s_rootSignature;
static ID3D12DescriptorHeap *s_cbvHeap;
static UINT s_cbvDescriptorSize;
static ID3D12PipelineState * s_pipelinestate;
static ID3D12Resource *s_constantBuffer;
static ID3D12Resource *s_vertexBuffer;
static ID3D12Resource *s_indexBuffer;
static ID3D12GraphicsCommandList *s_commandList;
static UINT8* s_mappedConstantBuffer;
static ModelViewProjectionConstantBuffer s_constantBufferData;
static const UINT c_alignedConstantBufferSize = (sizeof( ModelViewProjectionConstantBuffer ) + 255) & ~255ULL;

/* ---- tgUnit_Test__KN_GPU_Render_Context__Create_Resources ------------------------------------------------------------------------------------------------------------ */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgUnit_Test__KN_GPU_Render_Context__Create_Resources( C_TgKN_GPU_CXT_ID tiCXT )
{
    P_STg2_KN_GPU_Context               psCXT;
    P_STg2_KN_GPU_DX12_Context__Device  psCXT_DEVC;
    P_STg2_KN_GPU_DX12_Context__Output  psCXT_SWAP;
    P_STg2_KN_GPU_DX12_Context__Data    psCXT_DATA;
    P_D3D12_DEVICE1                     psDevice1;
    D3D12_DESCRIPTOR_RANGE range;
    D3D12_ROOT_PARAMETER parameter;
    P_D3D_BLOB pSignature;
    P_D3D_BLOB pError;
    D3D12_ROOT_SIGNATURE_DESC descRootSignature;
    STg2_KN_File_Open_Command sOpen_Command;
    STg2_KN_File_Read_Command sRead_Command_VS;
    STg2_KN_File_Read_Command sRead_Command_PS;
    D3D12_GRAPHICS_PIPELINE_STATE_DESC state;
    ID3D12Resource *vertexBufferUpload;
    D3D12_HEAP_PROPERTIES defaultHeapProperties;
    D3D12_RESOURCE_DESC sResource_Desc;
    D3D12_HEAP_PROPERTIES uploadHeapProperties;
    D3D12_SUBRESOURCE_DATA sSubresource_Data;
    D3D12_RESOURCE_BARRIER sResourceBarrier;
    UINT vertexBufferSize;
    ID3D12Resource *indexBufferUpload;
    D3D12_DESCRIPTOR_HEAP_DESC          sHeapDesc;

    psCXT = g_asKN_GPU_Context + tiCXT.m.iI;
    psCXT_DEVC = g_asKN_GPU_DX12_Context_Device + psCXT->m_tiCXT_DEVC.m.iI;
    psCXT_SWAP = g_asKN_GPU_DX12_Context_Output + psCXT->m_tiCXT_SWAP.m.iI;
    psCXT_DATA = g_asKN_GPU_DX12_Context_Data + psCXT->m_tiCXT_DATA.m.iI;
    psDevice1 = g_asKN_GPU_DXGI_Adapter[psCXT_DEVC->m_iAdapter].m_psDevice1;

    /* Create a root signature with a single constant buffer slot. */
    _CD3DX12_DESCRIPTOR_RANGE_Init( &range, D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0 );
    _CD3DX12_ROOT_PARAMETER_InitAsDescriptorTable( &parameter, 1, &range );
    parameter.ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;

    CLANG_WARN_SUPPRESS(assign-enum)
    _CD3DX12_ROOT_SIGNATURE_DESC_Init( &descRootSignature, 1, &parameter );
    descRootSignature.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |
                              D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS |
                              D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS |
                              D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS |
                              D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS;

    TgVERIFY(SUCCEEDED(g_pfnD3D12SerializeRootSignature( &descRootSignature, D3D_ROOT_SIGNATURE_VERSION_1, &pSignature, &pError )));
    TgVERIFY(SUCCEEDED(ID3D12Device1_CreateRootSignature( psDevice1, 0, ID3D10Blob_GetBufferPointer( pSignature ), ID3D10Blob_GetBufferSize( pSignature ),
                                                          &IID_ID3D12RootSignature, (PP_TgVOID)&s_rootSignature )));


    /* Read the Vertex and Pixel shaders */
    sOpen_Command.m_tiFS_Mount = g_tiKN_FS_HDD__Mount_APP;
    sOpen_Command.m_uiPath = KTgEMPTY_HASH;
    sOpen_Command.m_uiFile = tgSZ_Hash_File_Name(TgT("UnitTest_VS_001.cso"));
    sOpen_Command.m_enMode = ETgFILE_IO_ACCESS__READ;
    sOpen_Command.m_iCache = 0;
    sOpen_Command.m_pszFile_Name = nullptr;

    memset( &sRead_Command_VS, 0, sizeof( sRead_Command_VS ) );
    sRead_Command_VS.m_tiFile = tgKN_FS_BL_Open( &sOpen_Command );
    sRead_Command_VS.m_pfnAllocator = tgKN_FILE_ALLOCATOR__Default_Malloc_Pool;
    TgERROR(tgKN_FILE_ID_Is_Valid( sRead_Command_VS.m_tiFile ));
    TgVERIFY(SUCCEEDED(tgKN_FS_BL_Read( &sRead_Command_VS )));
    tgKN_FS_BL_Close( sRead_Command_VS.m_tiFile );

    sOpen_Command.m_uiFile = tgSZ_Hash_File_Name(TgT("UnitTest_PS_001.cso"));

    sRead_Command_PS = sRead_Command_VS;
    sRead_Command_PS.m_tiFile = tgKN_FS_BL_Open( &sOpen_Command );
    sRead_Command_PS.m_pBuffer = nullptr;
    sRead_Command_PS.m_nuiBuffer = 0;
    sRead_Command_PS.m_nuiResult = 0;
    TgERROR(tgKN_FILE_ID_Is_Valid( sRead_Command_PS.m_tiFile ));
    TgVERIFY(SUCCEEDED(tgKN_FS_BL_Read( &sRead_Command_PS )));
    tgKN_FS_BL_Close( sRead_Command_PS.m_tiFile );


    /* Create the pipeline state */
    const D3D12_INPUT_ELEMENT_DESC inputLayout[] =
    {
        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
        { "COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
    };

    memset( &state, 0, sizeof( state ) );
    state.InputLayout.pInputElementDescs = inputLayout;
    state.InputLayout.NumElements = 2;
    state.pRootSignature = s_rootSignature;
    _CD3DX12_SHADER_BYTECODE_Init_Shader_Code( &state.VS, sRead_Command_VS.m_pBuffer, sRead_Command_VS.m_nuiBuffer );
    _CD3DX12_SHADER_BYTECODE_Init_Shader_Code( &state.PS, sRead_Command_PS.m_pBuffer, sRead_Command_PS.m_nuiBuffer );
    _CD3DX12_RASTERIZER_DESC_Init_Default( &state.RasterizerState );
    _CD3DX12_BLEND_DESC_Init_Default( &state.BlendState );
    _CD3DX12_DEPTH_STENCIL_DESC_Init_Default( &state.DepthStencilState );
    state.SampleMask = UINT_MAX;
    state.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
    state.NumRenderTargets = 1;
    state.RTVFormats[0] = psCXT_SWAP->m_sMode.Format;
    state.DSVFormat = psCXT_SWAP->m_enFormat_DS;
    state.SampleDesc.Count = 1;

    TgVERIFY(SUCCEEDED(ID3D12Device1_CreateGraphicsPipelineState( psDevice1, &state, &IID_ID3D12PipelineState, (PP_TgVOID)&s_pipelinestate )));

    /* Shader data can be deleted once the pipeline state is created. */
    TgFREE_POOL( sRead_Command_VS.m_pBuffer );
    TgFREE_POOL( sRead_Command_PS.m_pBuffer );

    /* Create and upload cube geometry resources to the GPU. */

    TgVERIFY(SUCCEEDED(ID3D12Device1_CreateCommandList( psDevice1, psCXT_DEVC->m_uiNodeMask, D3D12_COMMAND_LIST_TYPE_DIRECT, psCXT_DEVC->m_psCmd_Allocator__Direct[0],
                                                        s_pipelinestate, &IID_ID3D12GraphicsCommandList, (PP_TgVOID)&s_commandList )));

    VertexPositionColor cubeVertices[] =
    {
        { { -0.5f, -0.5f, -0.5f }, { 0.0f, 0.0f, 0.0f } },
        { { -0.5f, -0.5f,  0.5f }, { 0.0f, 0.0f, 1.0f } },
        { { -0.5f,  0.5f, -0.5f }, { 0.0f, 1.0f, 0.0f } },
        { { -0.5f,  0.5f,  0.5f }, { 0.0f, 1.0f, 1.0f } },
        { {  0.5f, -0.5f, -0.5f }, { 1.0f, 0.0f, 0.0f } },
        { {  0.5f, -0.5f,  0.5f }, { 1.0f, 0.0f, 1.0f } },
        { {  0.5f,  0.5f, -0.5f }, { 1.0f, 1.0f, 0.0f } },
        { {  0.5f,  0.5f,  0.5f }, { 1.0f, 1.0f, 1.0f } },
    };

    vertexBufferSize = sizeof( cubeVertices );

    /* Create the vertex buffer resource in the GPU's default heap and copy vertex data into it using the upload heap.
       The upload resource must not be released until after the GPU has finished using it. */

    _CD3DX12_HEAP_PROPERTIES_Init_Type( &defaultHeapProperties, D3D12_HEAP_TYPE_DEFAULT );
    __CD3DX12_RESOURCE_DESC_Buffer( &sResource_Desc, vertexBufferSize );
    TgVERIFY(SUCCEEDED(ID3D12Device1_CreateCommittedResource( psDevice1, &defaultHeapProperties, D3D12_HEAP_FLAG_NONE, &sResource_Desc, D3D12_RESOURCE_STATE_COPY_DEST,
                                                              nullptr, &IID_ID3D12Resource, (PP_TgVOID)&s_vertexBuffer )));

    _CD3DX12_HEAP_PROPERTIES_Init_Type( &uploadHeapProperties, D3D12_HEAP_TYPE_UPLOAD );
    TgVERIFY(SUCCEEDED(ID3D12Device1_CreateCommittedResource( psDevice1, &uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &sResource_Desc, D3D12_RESOURCE_STATE_GENERIC_READ,
                                                              nullptr, &IID_ID3D12Resource, (PP_TgVOID)&vertexBufferUpload )));

    memset( &sSubresource_Data, 0, sizeof( sSubresource_Data ) );
    sSubresource_Data.pData = (BYTE*)(cubeVertices);
    sSubresource_Data.RowPitch = vertexBufferSize;
    sSubresource_Data.SlicePitch = sSubresource_Data.RowPitch;

    _D3DX12_UpdateSubresources_Heap( s_commandList, s_vertexBuffer, vertexBufferUpload, 0, 0, 1, &sSubresource_Data );

    __CD3DX12_RESOURCE_BARRIER_Transition( &sResourceBarrier, s_vertexBuffer, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER,
                                           D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, D3D12_RESOURCE_BARRIER_FLAG_NONE );
    ID3D12GraphicsCommandList_ResourceBarrier( s_commandList, 1, &sResourceBarrier );

    unsigned short cubeIndices[] =
    {
        0, 1, 2, // -x
        1, 3, 2,

        4, 6, 5, // +x
        5, 6, 7,

        0, 5, 1, // -y
        0, 4, 5,

        2, 7, 6, // +y
        2, 3, 7,

        0, 6, 4, // -z
        0, 2, 6,

        1, 7, 3, // +z
        1, 5, 7,
    };

    const UINT indexBufferSize = sizeof( cubeIndices );

    __CD3DX12_RESOURCE_DESC_Buffer( &sResource_Desc, indexBufferSize );
    TgVERIFY(SUCCEEDED(ID3D12Device1_CreateCommittedResource( psDevice1, &defaultHeapProperties, D3D12_HEAP_FLAG_NONE, &sResource_Desc, D3D12_RESOURCE_STATE_COPY_DEST,
                                                              nullptr, &IID_ID3D12Resource, (PP_TgVOID)&s_indexBuffer )));

    TgVERIFY(SUCCEEDED(ID3D12Device1_CreateCommittedResource( psDevice1, &uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &sResource_Desc, D3D12_RESOURCE_STATE_GENERIC_READ,
                                                              nullptr, &IID_ID3D12Resource, (PP_TgVOID)&indexBufferUpload )));

    sSubresource_Data.pData = (BYTE*)(cubeIndices);
    sSubresource_Data.RowPitch = indexBufferSize;
    sSubresource_Data.SlicePitch = sSubresource_Data.RowPitch;

    _D3DX12_UpdateSubresources_Heap( s_commandList, s_indexBuffer, indexBufferUpload, 0, 0, 1, &sSubresource_Data );

    __CD3DX12_RESOURCE_BARRIER_Transition( &sResourceBarrier, s_indexBuffer, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_INDEX_BUFFER,
                                           D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, D3D12_RESOURCE_BARRIER_FLAG_NONE );
    ID3D12GraphicsCommandList_ResourceBarrier( s_commandList, 1, &sResourceBarrier );

    memset( &sHeapDesc, 0, sizeof( sHeapDesc ) );
    sHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
    sHeapDesc.NodeMask = psCXT_DEVC->m_uiNodeMask;
    sHeapDesc.NumDescriptors = KTgKN_GPU_DX12_BUFFER_COUNT;
    sHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
    TgVERIFY(SUCCEEDED(ID3D12Device1_CreateDescriptorHeap( psDevice1, &sHeapDesc, &IID_ID3D12DescriptorHeap, (PP_TgVOID)&s_cbvHeap )));

    __CD3DX12_RESOURCE_DESC_Buffer( &sResource_Desc, KTgKN_GPU_DX12_BUFFER_COUNT * c_alignedConstantBufferSize );

    TgVERIFY(SUCCEEDED(ID3D12Device1_CreateCommittedResource( psDevice1, &uploadHeapProperties, D3D12_HEAP_FLAG_NONE, &sResource_Desc, D3D12_RESOURCE_STATE_GENERIC_READ,
                                                              nullptr, &IID_ID3D12Resource, (PP_TgVOID)&s_constantBuffer )));

    /* Create constant buffer views to access the upload buffer. */
    D3D12_GPU_VIRTUAL_ADDRESS cbvGpuAddress = __ID3D12Resource_GetGPUVirtualAddress( s_constantBuffer );
    D3D12_CPU_DESCRIPTOR_HANDLE cbvCpuHandle = __ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart( s_cbvHeap );
    s_cbvDescriptorSize = ID3D12Device1_GetDescriptorHandleIncrementSize( psDevice1, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV );

    for (int n = 0; n < KTgKN_GPU_DX12_BUFFER_COUNT; n++)
    {
        D3D12_CONSTANT_BUFFER_VIEW_DESC desc;
        desc.BufferLocation = cbvGpuAddress;
        desc.SizeInBytes = c_alignedConstantBufferSize;
        ID3D12Device1_CreateConstantBufferView( psDevice1, &desc, cbvCpuHandle );

        cbvGpuAddress += desc.SizeInBytes;
        cbvCpuHandle.ptr += s_cbvDescriptorSize;
    }

    // Map the constant buffers.
    D3D12_RANGE readRange;// We do not intend to read from this resource on the CPU.
    _CD3DX12_RANGE_Init( &readRange, 0, 0 );
    TgVERIFY(SUCCEEDED(ID3D12Resource_Map( s_constantBuffer, 0, &readRange, (PP_TgVOID)&s_mappedConstantBuffer )));
    memset( s_mappedConstantBuffer, 0, KTgKN_GPU_DX12_BUFFER_COUNT * c_alignedConstantBufferSize );

    /* Close the command list and execute it to begin the vertex/index buffer copy into the GPU's default heap. */
    TgVERIFY(SUCCEEDED(ID3D12GraphicsCommandList_Close( s_commandList )));
    ID3D12CommandQueue_ExecuteCommandLists( psCXT_DEVC->m_psCmd_Queue__Direct, 1, (PP_D3D12_COMMAND_LIST)&s_commandList );

    /* Create vertex/index buffer views. */
    s_vertexBufferView.BufferLocation = __ID3D12Resource_GetGPUVirtualAddress( s_vertexBuffer );
    s_vertexBufferView.StrideInBytes = sizeof( VertexPositionColor );
    s_vertexBufferView.SizeInBytes = sizeof( cubeVertices );

    s_indexBufferView.BufferLocation = __ID3D12Resource_GetGPUVirtualAddress( s_indexBuffer );
    s_indexBufferView.SizeInBytes = sizeof( cubeIndices );
    s_indexBufferView.Format = DXGI_FORMAT_R16_UINT;

    /* Wait for the command list to finish executing; the vertex/index buffers need to be uploaded to the GPU before the upload resources go out of scope. */
    tgKN_GPU_PM_Render_Context__Flush( psCXT->m_tiCXT_DEVC, psCXT->m_tiCXT_SWAP );

    DXGI_MODE_DESC1 sMode;
    float aspectRatio;
    float fovAngleY;
    TgVEC_F32_04 eye;
    TgVEC_F32_04 at;
    TgVEC_F32_04 up;

    sMode = psCXT_SWAP->m_sMode;
    aspectRatio = (float)sMode.Width / (float)sMode.Height;
    fovAngleY = 70.0f * KTgF_PI_F32 / 180.0f;

    eye = FS_SETP_F32_04( 0.0f, 0.7f, 1.5f );
    at = FS_SETP_F32_04( 0.0f, -0.1f, 0.0f );
    up = FS_SETV_F32_04( 0.0f, 1.0f, 0.0f );

    F_CLI_F32_44( &s_constantBufferData.model );
    F_LookLH_F32_44( &s_constantBufferData.view, &eye, &at, &up );
    FS_PProj_FoVLH_F32_44( &s_constantBufferData.projection, fovAngleY, aspectRatio, 0.01F, 100.0F );

    memcpy( s_mappedConstantBuffer + (0 * c_alignedConstantBufferSize), &s_constantBufferData, sizeof( s_constantBufferData ) );
    memcpy( s_mappedConstantBuffer + (1 * c_alignedConstantBufferSize), &s_constantBufferData, sizeof( s_constantBufferData ) );
    memcpy( s_mappedConstantBuffer + (2 * c_alignedConstantBufferSize), &s_constantBufferData, sizeof( s_constantBufferData ) );

    return (KTgS_OK);
}


/* ---- tgUnit_Test__KN_GPU_Render_Context__Render ---------------------------------------------------------------------------------------------------------------------- */
/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- */
TgRESULT tgUnit_Test__KN_GPU_Render_Context__Render( C_TgKN_GPU_CXT_ID tiCXT )
{
    P_STg2_KN_GPU_Context               psCXT;
    P_STg2_KN_GPU_DX12_Context__Device  psCXT_DEVC;
    P_STg2_KN_GPU_DX12_Context__Output  psCXT_SWAP;
    P_D3D12_DEVICE1                     psDevice1;
    D3D12_CPU_DESCRIPTOR_HANDLE         sHeap_RTV;
    D3D12_CPU_DESCRIPTOR_HANDLE         sHeap_DSV;
    D3D12_GPU_DESCRIPTOR_HANDLE         sHeap_GPU;
    TgFLOAT32                           afClearColor[4];

    psCXT = g_asKN_GPU_Context + tiCXT.m.iI;
    psCXT_DEVC = g_asKN_GPU_DX12_Context_Device + psCXT->m_tiCXT_DEVC.m.iI;
    psCXT_SWAP = g_asKN_GPU_DX12_Context_Output + psCXT->m_tiCXT_SWAP.m.iI;
    psDevice1 = g_asKN_GPU_DXGI_Adapter[psCXT_DEVC->m_iAdapter].m_psDevice1;

    afClearColor[0] = 0.5F * tgPM_SIN_F32(                           KTgF_PI_F32 * tgTM_Query_Time() * 0.0005F ) + 1.0F;
    afClearColor[1] = 0.5F * tgPM_SIN_F32( (2.F/3.F) * KTgF_PI_F32 + KTgF_PI_F32 * tgTM_Query_Time() * 0.0005F ) + 1.0F;
    afClearColor[2] = 0.5F * tgPM_SIN_F32( (4.F/3.F) * KTgF_PI_F32 + KTgF_PI_F32 * tgTM_Query_Time() * 0.0005F ) + 1.0F;
    afClearColor[3] = 1.0F;

    /* Can only be reset once no longer in flight on the GPU */
    TgVERIFY(SUCCEEDED(ID3D12GraphicsCommandList_Reset( psCXT_DEVC->m_psCmd_Graphics_List__Init, psCXT_DEVC->m_psCmd_Allocator__Direct[psCXT_SWAP->m_uiSwap_Index], nullptr )));

    ID3D12GraphicsCommandList_SetGraphicsRootSignature( psCXT_DEVC->m_psCmd_Graphics_List__Init, s_rootSignature );
    ID3D12GraphicsCommandList_SetDescriptorHeaps( psCXT_DEVC->m_psCmd_Graphics_List__Init, 1, &s_cbvHeap );

    sHeap_GPU = __ID3D12DescriptorHeap_GetGPUDescriptorHandleForHeapStart( s_cbvHeap );
    sHeap_GPU.ptr += psCXT_SWAP->m_uiSwap_Index * s_cbvDescriptorSize;
    ID3D12GraphicsCommandList_SetGraphicsRootDescriptorTable( psCXT_DEVC->m_psCmd_Graphics_List__Init, 0, sHeap_GPU );

    ID3D12GraphicsCommandList_RSSetViewports( psCXT_DEVC->m_psCmd_Graphics_List__Init, 1, &psCXT_SWAP->m_sViewPort );
    //ID3D12GraphicsCommandList_RSSetScissorRects( psCXT_DEVC->m_psCmd_Graphics_List__Init, 1, &psCXT_SWAP->m_sScissorRect );

    TgVERIFY(SUCCEEDED(ID3D12GraphicsCommandList_Close( psCXT_DEVC->m_psCmd_Graphics_List__Init )));

    ID3D12CommandQueue_ExecuteCommandLists( psCXT_DEVC->m_psCmd_Queue__Direct, 1, (PP_D3D12_COMMAND_LIST)&psCXT_DEVC->m_psCmd_Graphics_List__Init );

    tgKN_GPU_PM_Render_Context__Swap_Acquire( tiCXT );

    sHeap_RTV = __ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart( psCXT_DEVC->m_psHeap_RTV );
    sHeap_RTV.ptr += psCXT_SWAP->m_uiSwap_Index * psCXT_DEVC->m_uiDescriptor_Size_RTV;
    sHeap_DSV = __ID3D12DescriptorHeap_GetCPUDescriptorHandleForHeapStart( psCXT_DEVC->m_psHeap_DSV );
    ID3D12GraphicsCommandList_ClearRenderTargetView( psCXT_DEVC->m_psCmd_Graphics_List__Swap, sHeap_RTV, afClearColor, 0, nullptr );
    ID3D12GraphicsCommandList_ClearDepthStencilView( psCXT_DEVC->m_psCmd_Graphics_List__Swap, sHeap_DSV, D3D12_CLEAR_FLAG_DEPTH, 1.0F, 0, 0, nullptr );

    ID3D12GraphicsCommandList_OMSetRenderTargets( psCXT_DEVC->m_psCmd_Graphics_List__Swap, 1, &sHeap_RTV, 0, &sHeap_DSV );

    ID3D12GraphicsCommandList_IASetPrimitiveTopology( psCXT_DEVC->m_psCmd_Graphics_List__Swap, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
    ID3D12GraphicsCommandList_IASetVertexBuffers( psCXT_DEVC->m_psCmd_Graphics_List__Swap, 0, 1, &s_vertexBufferView );
    ID3D12GraphicsCommandList_IASetIndexBuffer( psCXT_DEVC->m_psCmd_Graphics_List__Swap, &s_indexBufferView );
    ID3D12GraphicsCommandList_DrawIndexedInstanced( psCXT_DEVC->m_psCmd_Graphics_List__Swap, 36, 1, 0, 0, 0 );

    tgKN_GPU_PM_Render_Context__Swap( tiCXT );
    return (KTgS_OK);
}