Home

Resume

Blog

Teikitu


/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
/*  »Project«   Teikitu Gaming System (TgS) (∂)
    »File«      TgS (DX12) Kernel - Internal - D3DX.inl
    »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".                                                   */
/* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
/* == Kernel ============================================================================================================================================================ */
#if !defined(TGS_DX12_KERNEL_INTERNAL_D3DX_INL)
#define TGS_DX12_KERNEL_INTERNAL_D3DX_INL

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

/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */
/*  Private GPU Functions                                                                                                                                                 */
/*    Reference: MSFT d3dx12.h - Translated to support both C and C++ using MSFT standard                                                                                 */
/* -.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-. */

/* -------------------------------------------------------------------------------- */
#if defined(CD3DX12_BOX_CLASS_DEFINED)

TgINLINE TgVOID _CD3DX12_BOX_LR(
    _Out_ D3D12_BOX *pBox,
    LONG Left,
    LONG Right )
{
    pBox->left = (UINT)Left;
    pBox->top = 0;
    pBox->front = 0;
    pBox->right = (UINT)Right;
    pBox->bottom = 1;
    pBox->back = 1;
}

TgINLINE TgVOID _CD3DX12_BOX_LTRB(
    _Out_ D3D12_BOX *pBox,
    LONG Left,
    LONG Top,
    LONG Right,
    LONG Bottom )
{
    pBox->left = (UINT)Left;
    pBox->top = (UINT)Top;
    pBox->front = 0;
    pBox->right = (UINT)Right;
    pBox->bottom = (UINT)Bottom;
    pBox->back = 1;
}

#endif     /* CD3DX12_BOX_CLASS_DEFINED */

/* -------------------------------------------------------------------------------- */
#if defined(CD3DX12_RANGE_CLASS_DEFINED)

TgINLINE TgVOID _CD3DX12_RANGE_Init(
    _Out_ D3D12_RANGE *pRange,
    SIZE_T begin,
    SIZE_T end )
{
    pRange->Begin = begin;
    pRange->End = end;
}

#endif     /* CD3DX12_RANGE_CLASS_DEFINED */

/* -------------------------------------------------------------------------------- */
#if defined(CD3DX12_TEXTURE_COPY_LOCATION_CLASS_DEFINED)

TgINLINE TgVOID _CD3DX12_TEXTURE_COPY_LOCATION_Init_Footprint(
    _Out_ D3D12_TEXTURE_COPY_LOCATION *pTex_Copy,
    ID3D12Resource* pRes,
    D3D12_PLACED_SUBRESOURCE_FOOTPRINT const *pFootprint )
{
    pTex_Copy->pResource = pRes;
    pTex_Copy->Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
    pTex_Copy->PlacedFootprint = *pFootprint;
}

TgINLINE TgVOID _CD3DX12_TEXTURE_COPY_LOCATION_Init_Sub_Resource(
    _Out_ D3D12_TEXTURE_COPY_LOCATION *pTex_Copy,
    ID3D12Resource* pRes,
    UINT Sub )
{
    pTex_Copy->pResource = pRes;
    pTex_Copy->Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
    pTex_Copy->SubresourceIndex = Sub;
}

#endif     /* CD3DX12_TEXTURE_COPY_LOCATION_CLASS_DEFINED */

/* -------------------------------------------------------------------------------- */
#if defined(CD3DX12_RESOURCE_BARRIER_CLASS_DEFINED)

TgINLINE TgVOID __CD3DX12_RESOURCE_BARRIER_Transition(
    _Out_ D3D12_RESOURCE_BARRIER* pResourceX,
    _In_ ID3D12Resource* pResource,
    D3D12_RESOURCE_STATES stateBefore,
    D3D12_RESOURCE_STATES stateAfter,
    UINT subresource,
    D3D12_RESOURCE_BARRIER_FLAGS flags )
{
    ZeroMemory( pResourceX, sizeof( D3D12_RESOURCE_BARRIER ) );
    pResourceX->Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
    pResourceX->Flags = flags;
    pResourceX->Transition.pResource = pResource;
    pResourceX->Transition.StateBefore = stateBefore;
    pResourceX->Transition.StateAfter = stateAfter;
    pResourceX->Transition.Subresource = subresource;
}

TgINLINE TgVOID __CD3DX12_RESOURCE_BARRIER_Aliasing(
    _Out_ D3D12_RESOURCE_BARRIER* pResourceX,
    _In_ ID3D12Resource* pResourceBefore,
    _In_ ID3D12Resource* pResourceAfter )
{
    ZeroMemory( pResourceX, sizeof( D3D12_RESOURCE_BARRIER ) );
    pResourceX->Type = D3D12_RESOURCE_BARRIER_TYPE_ALIASING;
    pResourceX->Aliasing.pResourceBefore = pResourceBefore;
    pResourceX->Aliasing.pResourceAfter = pResourceAfter;
}

TgINLINE TgVOID __CD3DX12_RESOURCE_BARRIER_UAV(
    _Out_ D3D12_RESOURCE_BARRIER* pResourceX,
    _In_ ID3D12Resource* pResource )
{
    ZeroMemory( pResourceX, sizeof( D3D12_RESOURCE_BARRIER ) );
    pResourceX->Type = D3D12_RESOURCE_BARRIER_TYPE_UAV;
    pResourceX->UAV.pResource = pResource;
}

#endif /* CD3DX12_RESOURCE_BARRIER_CLASS_DEFINED */

/* -------------------------------------------------------------------------------- */
#if defined(CD3DX12_RESOURCE_DESC_CLASS_DEFINED)

TgINLINE UINT D3D12CalcSubresource( UINT MipSlice, UINT ArraySlice, UINT PlaneSlice, UINT MipLevels, UINT ArraySize )
{
    return MipSlice + ArraySlice * MipLevels + PlaneSlice * MipLevels * ArraySize;
}

TgINLINE UINT8 D3D12GetFormatPlaneCount( _In_ ID3D12Device* pDevice, DXGI_FORMAT Format )
{
    D3D12_FEATURE_DATA_FORMAT_INFO formatInfo;

    memset( &formatInfo, 0, sizeof( formatInfo ) );
    formatInfo.Format = Format;

    if (FAILED(ID3D12Device_CheckFeatureSupport( pDevice, D3D12_FEATURE_FORMAT_INFO, &formatInfo, sizeof( formatInfo ) )))
    {
        return 0;
    }
    return formatInfo.PlaneCount;
}

TgINLINE TgVOID __CD3DX12_RESOURCE_DESC_Buffer_From_AllococationInfo(
    _Out_ D3D12_RESOURCE_DESC* pResourceX,
    const D3D12_RESOURCE_ALLOCATION_INFO *pResAllocInfo )
{
    pResourceX->Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
    pResourceX->Alignment = pResAllocInfo->Alignment;
    pResourceX->Width = pResAllocInfo->SizeInBytes;
    pResourceX->Height = 1;
    pResourceX->DepthOrArraySize = 1;
    pResourceX->MipLevels = 1;
    pResourceX->Format = DXGI_FORMAT_UNKNOWN;
    pResourceX->SampleDesc.Count = 1;
    pResourceX->SampleDesc.Quality = 0;
    pResourceX->Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
    pResourceX->Flags = D3D12_RESOURCE_FLAG_NONE;
}

TgINLINE TgVOID __CD3DX12_RESOURCE_DESC_Buffer(
    _Out_ D3D12_RESOURCE_DESC* pResourceX,
    UINT64 width )
{
    pResourceX->Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
    pResourceX->Alignment = 0;
    pResourceX->Width = width;
    pResourceX->Height = 1;
    pResourceX->DepthOrArraySize = 1;
    pResourceX->MipLevels = 1;
    pResourceX->Format = DXGI_FORMAT_UNKNOWN;
    pResourceX->SampleDesc.Count = 1;
    pResourceX->SampleDesc.Quality = 0;
    pResourceX->Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
    pResourceX->Flags = D3D12_RESOURCE_FLAG_NONE;
}

TgINLINE TgVOID __CD3DX12_RESOURCE_DESC_Tex1D(
    _Out_ D3D12_RESOURCE_DESC* pResourceX,
    DXGI_FORMAT format,
    UINT64 width )
{
    pResourceX->Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE1D;
    pResourceX->Alignment = 0;
    pResourceX->Width = width;
    pResourceX->Height = 1;
    pResourceX->DepthOrArraySize = 1;
    pResourceX->MipLevels = 0;
    pResourceX->Format = format;
    pResourceX->SampleDesc.Count = 1;
    pResourceX->SampleDesc.Quality = 0;
    pResourceX->Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
    pResourceX->Flags = D3D12_RESOURCE_FLAG_NONE;
}

TgINLINE TgVOID __CD3DX12_RESOURCE_DESC_Tex2D(
    _Out_ D3D12_RESOURCE_DESC* pResourceX,
    DXGI_FORMAT format,
    UINT64 width,
    UINT height )
{
    pResourceX->Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D;
    pResourceX->Alignment = 0;
    pResourceX->Width = width;
    pResourceX->Height = height;
    pResourceX->DepthOrArraySize = 1;
    pResourceX->MipLevels = 0;
    pResourceX->Format = format;
    pResourceX->SampleDesc.Count = 1;
    pResourceX->SampleDesc.Quality = 0;
    pResourceX->Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
    pResourceX->Flags = D3D12_RESOURCE_FLAG_NONE;
}

TgINLINE TgVOID __CD3DX12_RESOURCE_DESC_Tex3D(
    _Out_ D3D12_RESOURCE_DESC* pResourceX,
    DXGI_FORMAT format,
    UINT64 width,
    UINT height,
    UINT16 depth )
{
    pResourceX->Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE3D;
    pResourceX->Alignment = 0;
    pResourceX->Width = width;
    pResourceX->Height = height;
    pResourceX->DepthOrArraySize = depth;
    pResourceX->MipLevels = 0;
    pResourceX->Format = format;
    pResourceX->SampleDesc.Count = 1;
    pResourceX->SampleDesc.Quality = 0;
    pResourceX->Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN;
    pResourceX->Flags = D3D12_RESOURCE_FLAG_NONE;
}

TgINLINE UINT16 __CD3DX12_RESOURCE_DESC_Depth( _In_ const D3D12_RESOURCE_DESC* pResourceX )
{
    return (pResourceX->Dimension == D3D12_RESOURCE_DIMENSION_TEXTURE3D ? pResourceX->DepthOrArraySize : 1u);
}

TgINLINE UINT16 __CD3DX12_RESOURCE_DESC_ArraySize( _In_ const D3D12_RESOURCE_DESC* pResourceX )
{
    return (pResourceX->Dimension != D3D12_RESOURCE_DIMENSION_TEXTURE3D ? pResourceX->DepthOrArraySize : 1u);
}

TgINLINE UINT8 __CD3DX12_RESOURCE_DESC_PlaneCount( _In_ const D3D12_RESOURCE_DESC* pResourceX, _In_ ID3D12Device* pDevice )
{
    return D3D12GetFormatPlaneCount(pDevice, pResourceX->Format);
}

TgINLINE UINT __CD3DX12_RESOURCE_DESC_Subresources( _In_ const D3D12_RESOURCE_DESC* pResourceX, _In_ ID3D12Device* pDevice )
{
    return (UINT)(pResourceX->MipLevels * __CD3DX12_RESOURCE_DESC_ArraySize( pResourceX ) * __CD3DX12_RESOURCE_DESC_PlaneCount( pResourceX, pDevice ));
}

TgINLINE UINT __CD3DX12_RESOURCE_DESC_CalcSubresource( _In_ D3D12_RESOURCE_DESC* pResourceX, UINT MipSlice, UINT ArraySlice, UINT PlaneSlice )
{
    return D3D12CalcSubresource(MipSlice, ArraySlice, PlaneSlice, pResourceX->MipLevels, __CD3DX12_RESOURCE_DESC_ArraySize( pResourceX ));
}

#endif     /* CD3DX12_RESOURCE_DESC_CLASS_DEFINED */


/* -------------------------------------------------------------------------------- */
#if defined(CD3DX12_DESCRIPTOR_RANGE_CLASS_DEFINED)

TgINLINE TgVOID _CD3DX12_DESCRIPTOR_RANGE_Init(
    _Out_ D3D12_DESCRIPTOR_RANGE *pRange,
    D3D12_DESCRIPTOR_RANGE_TYPE rangeType,
    UINT numDescriptors,
    UINT baseShaderRegister )
{
    pRange->RangeType = rangeType;
    pRange->NumDescriptors = numDescriptors;
    pRange->BaseShaderRegister = baseShaderRegister;
    pRange->RegisterSpace = 0;
    pRange->OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
}

#endif     /* CD3DX12_DESCRIPTOR_RANGE_CLASS_DEFINED */

/* -------------------------------------------------------------------------------- */
#if defined(CD3DX12_ROOT_DESCRIPTOR_TABLE_CLASS_DEFINED)

TgINLINE TgVOID _CD3DX12_ROOT_DESCRIPTOR_TABLE_Init(
    _Out_ D3D12_ROOT_DESCRIPTOR_TABLE *pRootDescriptorTable,
    UINT numDescriptorRanges,
    _In_reads_opt_( numDescriptorRanges ) const D3D12_DESCRIPTOR_RANGE* _pDescriptorRanges )
{
    pRootDescriptorTable->NumDescriptorRanges = numDescriptorRanges;
    pRootDescriptorTable->pDescriptorRanges = _pDescriptorRanges;
}

#endif     /* CD3DX12_ROOT_DESCRIPTOR_TABLE_CLASS_DEFINED */

/* -------------------------------------------------------------------------------- */
#if defined(CD3DX12_ROOT_CONSTANTS_CLASS_DEFINED)

TgINLINE TgVOID _CD3DX12_ROOT_CONSTANTS_Init(
    _Out_ D3D12_ROOT_CONSTANTS *pRootConstants,
    UINT num32BitValues,
    UINT shaderRegister )
{
    pRootConstants->Num32BitValues = num32BitValues;
    pRootConstants->ShaderRegister = shaderRegister;
    pRootConstants->RegisterSpace = 0;
}

#endif     /* CD3DX12_ROOT_CONSTANTS_CLASS_DEFINED */

/* -------------------------------------------------------------------------------- */
#if defined(CD3DX12_ROOT_DESCRIPTOR_CLASS_DEFINED)

TgINLINE TgVOID _CD3DX12_ROOT_DESCRIPTOR_Init(
    _Out_ D3D12_ROOT_DESCRIPTOR *pTable,
    UINT shaderRegister )
{
    pTable->ShaderRegister = shaderRegister;
    pTable->RegisterSpace = 0;
}

#endif     /* CD3DX12_ROOT_DESCRIPTOR_CLASS_DEFINED */

/* -------------------------------------------------------------------------------- */
#if defined(CD3DX12_ROOT_PARAMETER_CLASS_DEFINED)

TgINLINE TgVOID _CD3DX12_ROOT_PARAMETER_InitAsDescriptorTable(
    _Out_ D3D12_ROOT_PARAMETER *pRootParam,
    UINT numDescriptorRanges,
    _In_reads_(numDescriptorRanges) const D3D12_DESCRIPTOR_RANGE* pDescriptorRanges )
{
    pRootParam->ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
    pRootParam->ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
    _CD3DX12_ROOT_DESCRIPTOR_TABLE_Init( &pRootParam->DescriptorTable, numDescriptorRanges, pDescriptorRanges);
}

TgINLINE TgVOID _CD3DX12_ROOT_PARAMETER_InitAsConstants(
    _Out_ D3D12_ROOT_PARAMETER *pRootParam,
    UINT num32BitValues,
    UINT shaderRegister )
{
    pRootParam->ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
    pRootParam->ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
    _CD3DX12_ROOT_CONSTANTS_Init( &pRootParam->Constants, num32BitValues, shaderRegister );
}

TgINLINE TgVOID _CD3DX12_ROOT_PARAMETER_InitAsConstantBufferView(
    _Out_ D3D12_ROOT_PARAMETER *pRootParam,
    UINT shaderRegister )
{
    pRootParam->ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
    pRootParam->ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
    _CD3DX12_ROOT_DESCRIPTOR_Init( &pRootParam->Descriptor, shaderRegister );
}

TgINLINE TgVOID _CD3DX12_ROOT_PARAMETER_InitAsShaderResourceView(
    _Out_ D3D12_ROOT_PARAMETER *pRootParam,
    UINT shaderRegister )
{
    pRootParam->ParameterType = D3D12_ROOT_PARAMETER_TYPE_SRV;
    pRootParam->ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
    _CD3DX12_ROOT_DESCRIPTOR_Init( &pRootParam->Descriptor, shaderRegister );
}

TgINLINE TgVOID _CD3DX12_ROOT_PARAMETER_InitAsUnorderedAccessView(
    _Out_ D3D12_ROOT_PARAMETER *pRootParam,
    UINT shaderRegister )
{
    pRootParam->ParameterType = D3D12_ROOT_PARAMETER_TYPE_UAV;
    pRootParam->ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
    _CD3DX12_ROOT_DESCRIPTOR_Init( &pRootParam->Descriptor, shaderRegister );
}

#endif     /* CD3DX12_ROOT_PARAMETER_CLASS_DEFINED */

/* -------------------------------------------------------------------------------- */
#if defined(CD3DX12_ROOT_SIGNATURE_DESC_CLASS_DEFINED)

TgINLINE TgVOID _CD3DX12_ROOT_SIGNATURE_DESC_Init(
    _Out_ D3D12_ROOT_SIGNATURE_DESC *pDesc,
    UINT numParameters,
    _In_reads_opt_(numParameters) const D3D12_ROOT_PARAMETER* _pParameters )
{
    pDesc->NumParameters = numParameters;
    pDesc->pParameters = _pParameters;
    pDesc->NumStaticSamplers = 0;
    pDesc->pStaticSamplers = nullptr;
    pDesc->Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE;
}

#endif     /* CD3DX12_ROOT_SIGNATURE_DESC_CLASS_DEFINED */

/* -------------------------------------------------------------------------------- */
#if defined(CD3DX12_SHADER_BYTECODE_CLASS_DEFINED)

TgINLINE TgVOID _CD3DX12_SHADER_BYTECODE_Init_Blob(
    _Out_ D3D12_SHADER_BYTECODE *pShader,
    ID3DBlob* pShaderBlob )
{
    pShader->pShaderBytecode = ID3D10Blob_GetBufferPointer( pShaderBlob );
    pShader->BytecodeLength = ID3D10Blob_GetBufferSize( pShaderBlob );
}

TgINLINE TgVOID _CD3DX12_SHADER_BYTECODE_Init_Shader_Code(
    _Out_ D3D12_SHADER_BYTECODE *pShader,
    void* _pShaderBytecode,
    SIZE_T bytecodeLength )
{
    pShader->pShaderBytecode = _pShaderBytecode;
    pShader->BytecodeLength = bytecodeLength;
}

#endif     /* CD3DX12_SHADER_BYTECODE_CLASS_DEFINED */

/* -------------------------------------------------------------------------------- */
#if defined(CD3DX12_DEPTH_STENCIL_DESC_CLASS_DEFINED)

TgINLINE TgVOID _CD3DX12_DEPTH_STENCIL_DESC_Init_Default(
    _Out_ D3D12_DEPTH_STENCIL_DESC *pDS )
{
    const D3D12_DEPTH_STENCILOP_DESC defaultStencilOp =
    { D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_STENCIL_OP_KEEP, D3D12_COMPARISON_FUNC_ALWAYS };

    pDS->DepthEnable = TRUE;
    pDS->DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ALL;
    pDS->DepthFunc = D3D12_COMPARISON_FUNC_LESS;
    pDS->StencilEnable = FALSE;
    pDS->StencilReadMask = D3D12_DEFAULT_STENCIL_READ_MASK;
    pDS->StencilWriteMask = D3D12_DEFAULT_STENCIL_WRITE_MASK;
    pDS->FrontFace = defaultStencilOp;
    pDS->BackFace = defaultStencilOp;
}

#endif     /* CD3DX12_DEPTH_STENCIL_DESC_CLASS_DEFINED */

/* -------------------------------------------------------------------------------- */
#if defined(CD3DX12_BLEND_DESC_CLASS_DEFINED)

TgINLINE TgVOID _CD3DX12_BLEND_DESC_Init_Default(
    _Out_ D3D12_BLEND_DESC *pBlend )
{
    const D3D12_RENDER_TARGET_BLEND_DESC defaultRenderTargetBlendDesc =
    {
        FALSE,FALSE,
        D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,
        D3D12_BLEND_ONE, D3D12_BLEND_ZERO, D3D12_BLEND_OP_ADD,
        D3D12_LOGIC_OP_NOOP,
        D3D12_COLOR_WRITE_ENABLE_ALL,
    };

    pBlend->AlphaToCoverageEnable = FALSE;
    pBlend->IndependentBlendEnable = FALSE;
    for (UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)
        pBlend->RenderTarget[i] = defaultRenderTargetBlendDesc;
}

#endif     /* CD3DX12_BLEND_DESC_CLASS_DEFINED */

/* -------------------------------------------------------------------------------- */
#if defined(CD3DX12_RASTERIZER_DESC_CLASS_DEFINED)

TgINLINE TgVOID _CD3DX12_RASTERIZER_DESC_Init_Default(
    _Out_ D3D12_RASTERIZER_DESC *pRast )
{
    pRast->FillMode = D3D12_FILL_MODE_SOLID;
    pRast->CullMode = D3D12_CULL_MODE_BACK;
    pRast->FrontCounterClockwise = FALSE;
    pRast->DepthBias = D3D12_DEFAULT_DEPTH_BIAS;
    pRast->DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;
    pRast->SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;
    pRast->DepthClipEnable = TRUE;
    pRast->MultisampleEnable = FALSE;
    pRast->AntialiasedLineEnable = FALSE;
    pRast->ForcedSampleCount = 0;
    pRast->ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
}

#endif     /* CD3DX12_RASTERIZER_DESC_CLASS_DEFINED */

/* -------------------------------------------------------------------------------- */
#if defined(CD3DX12_HEAP_PROPERTIES_CLASS_DEFINED)

TgINLINE TgVOID _CD3DX12_HEAP_PROPERTIES_Init_Custom(
    _Out_ D3D12_HEAP_PROPERTIES *pHeap_Property,
    D3D12_CPU_PAGE_PROPERTY cpuPageProperty, 
    D3D12_MEMORY_POOL memoryPoolPreference )
{
    pHeap_Property->Type = D3D12_HEAP_TYPE_CUSTOM;
    pHeap_Property->CPUPageProperty = cpuPageProperty;
    pHeap_Property->MemoryPoolPreference = memoryPoolPreference;
    pHeap_Property->CreationNodeMask = 1;
    pHeap_Property->VisibleNodeMask = 1;
}

TgINLINE TgVOID _CD3DX12_HEAP_PROPERTIES_Init_Type(
    _Out_ D3D12_HEAP_PROPERTIES *pHeap_Property,
    D3D12_HEAP_TYPE type )
{
    pHeap_Property->Type = type;
    pHeap_Property->CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
    pHeap_Property->MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
    pHeap_Property->CreationNodeMask = 1;
    pHeap_Property->VisibleNodeMask = 1;
}

TgINLINE TgBOOL _CD3DX12_HEAP_PROPERTIES_IsCPUAccessible(
    _In_ D3D12_HEAP_PROPERTIES *pHeap_Property )
{
    return (pHeap_Property->Type == D3D12_HEAP_TYPE_UPLOAD ||
            pHeap_Property->Type == D3D12_HEAP_TYPE_READBACK ||
            (
                pHeap_Property->Type == D3D12_HEAP_TYPE_CUSTOM &&
                (
                    pHeap_Property->CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_COMBINE ||
                    pHeap_Property->CPUPageProperty == D3D12_CPU_PAGE_PROPERTY_WRITE_BACK
                )
            )) ? TgTRUE : TgFALSE;
}

#endif     /* CD3DX12_HEAP_PROPERTIES_CLASS_DEFINED */

//------------------------------------------------------------------------------------------------
// Row-by-row memcpy
TgINLINE TgVOID MemcpySubresource(
    _In_ const D3D12_MEMCPY_DEST* pDest,
    _In_ const D3D12_SUBRESOURCE_DATA* pSrc,
    SIZE_T RowSizeInBytes,
    UINT NumRows,
    UINT NumSlices)
{
    for (UINT z = 0; z < NumSlices; ++z)
    {
        BYTE* pDestSlice = (BYTE*)(pDest->pData) + pDest->SlicePitch * z;
        const BYTE* pSrcSlice = (const BYTE*)(pSrc->pData) + pSrc->SlicePitch * z;
        for (UINT y = 0; y < NumRows; ++y)
        {
            memcpy(pDestSlice + pDest->RowPitch * y,
                   pSrcSlice + pSrc->RowPitch * y,
                   RowSizeInBytes);
        }
    }
}

/* -------------------------------------------------------------------------------- */
/* All arrays must be populated (e.g. by calling GetCopyableFootprints) */
TgINLINE UINT64 _D3DX12_UpdateSubresources(
    _In_ ID3D12GraphicsCommandList* pCmdList,
    _In_ ID3D12Resource* pDestinationResource,
    _In_ ID3D12Resource* pIntermediate,
    _In_range_( 0, D3D12_REQ_SUBRESOURCES ) UINT FirstSubresource,
    _In_range_( 0, D3D12_REQ_SUBRESOURCES - FirstSubresource ) UINT NumSubresources,
    UINT64 RequiredSize,
    _In_reads_( NumSubresources ) const D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts,
    _In_reads_( NumSubresources ) const UINT* pNumRows,
    _In_reads_( NumSubresources ) const UINT64* pRowSizesInBytes,
    _In_reads_( NumSubresources ) const D3D12_SUBRESOURCE_DATA* pSrcData )
{
    D3D12_RESOURCE_DESC IntermediateDesc;
    D3D12_RESOURCE_DESC DestinationDesc;
    BYTE* pData;
    HRESULT hr;

    // Minor validation
    IntermediateDesc = __ID3D12Resource_GetDesc( pIntermediate );
    DestinationDesc = __ID3D12Resource_GetDesc( pDestinationResource );

    if (IntermediateDesc.Dimension != D3D12_RESOURCE_DIMENSION_BUFFER ||
         IntermediateDesc.Width < RequiredSize + pLayouts[0].Offset ||
         RequiredSize >( SIZE_T ) - 1 ||
         (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER &&
         (FirstSubresource != 0 || NumSubresources != 1)))
    {
        return 0;
    }

    hr = ID3D12Resource_Map( pIntermediate, 0, NULL, (PP_TgVOID)&pData );
    if (FAILED( hr ))
    {
        return 0;
    }

    for (UINT i = 0; i < NumSubresources; ++i)
    {
        D3D12_MEMCPY_DEST DestData;

        if (pRowSizesInBytes[i] > ( SIZE_T )-1)
            return 0;

        DestData.pData = pData + pLayouts[i].Offset;
        DestData.RowPitch = pLayouts[i].Footprint.RowPitch;
        DestData.SlicePitch = pLayouts[i].Footprint.RowPitch * pNumRows[i];
        MemcpySubresource( &DestData, &pSrcData[i], (SIZE_T)pRowSizesInBytes[i], pNumRows[i], pLayouts[i].Footprint.Depth );
    }
    ID3D12Resource_Unmap( pIntermediate, 0, NULL );

    if (DestinationDesc.Dimension == D3D12_RESOURCE_DIMENSION_BUFFER)
    {
        D3D12_BOX SrcBox;

        _CD3DX12_BOX_LR( &SrcBox, (LONG)pLayouts[0].Offset, (LONG)(pLayouts[0].Offset + pLayouts[0].Footprint.Width) );
        ID3D12GraphicsCommandList_CopyBufferRegion( pCmdList, pDestinationResource, 0, pIntermediate, pLayouts[0].Offset, pLayouts[0].Footprint.Width );
    }
    else
    {
        for (UINT i = 0; i < NumSubresources; ++i)
        {
            D3D12_TEXTURE_COPY_LOCATION Dst;
            D3D12_TEXTURE_COPY_LOCATION Src;

            _CD3DX12_TEXTURE_COPY_LOCATION_Init_Sub_Resource( &Dst, pDestinationResource, i + FirstSubresource );
            _CD3DX12_TEXTURE_COPY_LOCATION_Init_Footprint( &Src, pIntermediate, pLayouts + i );
            ID3D12GraphicsCommandList_CopyTextureRegion( pCmdList, &Dst, 0, 0, 0, &Src, nullptr );
        }
    }
    return RequiredSize;
}

/* -------------------------------------------------------------------------------- */
/* Heap-allocating UpdateSubresources implementation */
TgINLINE UINT64 _D3DX12_UpdateSubresources_Heap(
    _In_ ID3D12GraphicsCommandList* pCmdList,
    _In_ ID3D12Resource* pDestinationResource,
    _In_ ID3D12Resource* pIntermediate,
    UINT64 IntermediateOffset,
    _In_range_( 0, D3D12_REQ_SUBRESOURCES ) UINT FirstSubresource,
    _In_range_( 0, D3D12_REQ_SUBRESOURCES - FirstSubresource ) UINT NumSubresources,
    _In_reads_( NumSubresources ) D3D12_SUBRESOURCE_DATA* pSrcData )
{
    UINT64 RequiredSize;
    UINT64 MemToAlloc;
    void* pMem;
    D3D12_PLACED_SUBRESOURCE_FOOTPRINT* pLayouts;
    UINT64* pRowSizesInBytes;
    UINT* pNumRows;
    D3D12_RESOURCE_DESC Desc;
    ID3D12Device* pDevice;
    UINT64 Result;

    RequiredSize = 0;
    MemToAlloc = (UINT64)(sizeof( D3D12_PLACED_SUBRESOURCE_FOOTPRINT ) + sizeof( UINT ) + sizeof( UINT64 )) * NumSubresources;
    if (MemToAlloc > SIZE_MAX)
    {
        return 0;
    }
    pMem = HeapAlloc( GetProcessHeap(), 0, (SIZE_T)(MemToAlloc) );
    if (pMem == NULL)
    {
        return 0;
    }
    pLayouts = (D3D12_PLACED_SUBRESOURCE_FOOTPRINT*)(pMem);
    pRowSizesInBytes = (UINT64*)(pLayouts + NumSubresources);
    pNumRows = (UINT*)(pRowSizesInBytes + NumSubresources);

    Desc = __ID3D12Resource_GetDesc( pDestinationResource );
    ID3D12Resource_GetDevice( pDestinationResource, &IID_ID3D12Device, (PP_TgVOID)&pDevice );
    ID3D12Device_GetCopyableFootprints( pDevice, &Desc, FirstSubresource, NumSubresources, IntermediateOffset, pLayouts, pNumRows, pRowSizesInBytes, &RequiredSize );
    ID3D12Device_Release( pDevice );

    Result = _D3DX12_UpdateSubresources( pCmdList, pDestinationResource, pIntermediate, FirstSubresource, NumSubresources, RequiredSize, pLayouts, pNumRows, pRowSizesInBytes, pSrcData );
    HeapFree( GetProcessHeap(), 0, pMem );
    return Result;
}


/* ====================================================================================================================================================================== */
#endif