CommandContext* RenderDeviceD3D12Impl::AllocateCommandContext(const Char *ID)
{
	std::lock_guard<std::mutex> LockGuard(m_ContextAllocationMutex);

	CommandContext* ret = nullptr;
	if (m_AvailableContexts.empty())
	{
        auto &CmdCtxAllocator = GetRawAllocator();
        auto *pRawMem = ALLOCATE(CmdCtxAllocator, "CommandContext instance", sizeof(CommandContext));
		ret = new (pRawMem) CommandContext( GetRawAllocator(), m_CmdListManager, m_GPUDescriptorHeaps, m_DynamicDescriptorAllocationChunkSize);
		m_ContextPool.emplace_back(ret, STDDeleterRawMem<CommandContext>(CmdCtxAllocator) );
	}
	else
	{
		ret = m_AvailableContexts.front();
		m_AvailableContexts.pop_front();
		ret->Reset(m_CmdListManager);
	}
	VERIFY_EXPR(ret != nullptr);
	ret->SetID(ID);
	//if ( ID != nullptr && *ID != 0 )
	//	EngineProfiling::BeginBlock(ID, NewContext);

	return ret;
}
DynamicUploadHeap* RenderDeviceD3D12Impl::RequestUploadHeap()
{
    std::lock_guard<std::mutex> LockGuard(m_UploadHeapMutex);

#ifdef _DEBUG
    size_t InitialSize = 1024+64;
#else
    size_t InitialSize = 64<<10;//16<<20;
#endif

    auto &UploadHeapAllocator = GetRawAllocator();
    auto *pRawMem = ALLOCATE(UploadHeapAllocator, "DynamicUploadHeap instance", sizeof(DynamicUploadHeap));
    auto *pNewHeap = new (pRawMem) DynamicUploadHeap(GetRawAllocator(), true, this, InitialSize);
    m_UploadHeaps.emplace_back( pNewHeap, STDDeleterRawMem<DynamicUploadHeap>(UploadHeapAllocator) );
    return pNewHeap;
}
 DynamicUploadHeap::DynamicUploadHeap(IMemoryAllocator &Allocator, bool bIsCPUAccessible, class RenderDeviceD3D12Impl* pDevice, size_t InitialSize) :
     m_Allocator(Allocator),
     m_pDeviceD3D12(pDevice),
     m_bIsCPUAccessible(bIsCPUAccessible),
     m_RingBuffers(STD_ALLOCATOR_RAW_MEM(GPURingBuffer, GetRawAllocator(), "Allocator for vector<GPURingBuffer>"))
 {
     m_RingBuffers.emplace_back(InitialSize, Allocator, pDevice->GetD3D12Device(), m_bIsCPUAccessible);
 }
/// \param [in] CreationAttribs - Engine creation attributes.
/// \param [out] ppDevice - Address of the memory location where pointer to 
///                         the created device will be written.
/// \param [out] ppImmediateContext - Address of the memory location where pointers to 
///                                   the immediate context will be written.
void EngineFactoryOpenGLImpl::AttachToActiveGLContext( const EngineGLAttribs& CreationAttribs,
                                                       IRenderDevice **ppDevice,
                                                       IDeviceContext **ppImmediateContext )
{
    if (CreationAttribs.DebugMessageCallback != nullptr)
        SetDebugMessageCallback(CreationAttribs.DebugMessageCallback);

    VERIFY( ppDevice && ppImmediateContext, "Null pointer provided" );
    if( !ppDevice || !ppImmediateContext )
        return;

    *ppDevice = nullptr;
    *ppImmediateContext = nullptr;

    try
    {
        SetRawAllocator(CreationAttribs.pRawMemAllocator);
        auto &RawMemAllocator = GetRawAllocator();

        RenderDeviceGLImpl *pRenderDeviceOpenGL( NEW_RC_OBJ(RawMemAllocator, "TRenderDeviceGLImpl instance", TRenderDeviceGLImpl)(RawMemAllocator, CreationAttribs) );
        pRenderDeviceOpenGL->QueryInterface(IID_RenderDevice, reinterpret_cast<IObject**>(ppDevice) );

        DeviceContextGLImpl *pDeviceContextOpenGL( NEW_RC_OBJ(RawMemAllocator, "DeviceContextGLImpl instance", DeviceContextGLImpl)(pRenderDeviceOpenGL, false ) );
        // We must call AddRef() (implicitly through QueryInterface()) because pRenderDeviceOpenGL will
        // keep a weak reference to the context
        pDeviceContextOpenGL->QueryInterface(IID_DeviceContext, reinterpret_cast<IObject**>(ppImmediateContext) );
        pRenderDeviceOpenGL->SetImmediateContext(pDeviceContextOpenGL);
    }
    catch( const std::runtime_error & )
    {
        if( *ppDevice )
        {
            (*ppDevice)->Release();
            *ppDevice = nullptr;
        }

        if( *ppImmediateContext )
        {
            (*ppImmediateContext)->Release();
            *ppImmediateContext = nullptr;
        }

        LOG_ERROR( "Failed to initialize OpenGL-based render device" );
    }
}
Texture1D_D3D11 :: Texture1D_D3D11(IReferenceCounters *pRefCounters,
                                   FixedBlockMemoryAllocator &TexViewObjAllocator, 
                                   RenderDeviceD3D11Impl *pRenderDeviceD3D11, 
                                   const TextureDesc& TexDesc, 
                                   const TextureData &InitData /*= TextureData()*/) : 
    TextureBaseD3D11(pRefCounters, TexViewObjAllocator, pRenderDeviceD3D11, TexDesc, InitData)
{
    auto D3D11TexFormat = TexFormatToDXGI_Format(m_Desc.Format, m_Desc.BindFlags);
    auto D3D11BindFlags = BindFlagsToD3D11BindFlags(m_Desc.BindFlags);
    auto D3D11CPUAccessFlags = CPUAccessFlagsToD3D11CPUAccessFlags(m_Desc.CPUAccessFlags);
    auto D3D11Usage = UsageToD3D11Usage(m_Desc.Usage);
    UINT MiscFlags = MiscTextureFlagsToD3D11Flags(m_Desc.MiscFlags);
    auto *pDeviceD3D11 = pRenderDeviceD3D11->GetD3D11Device();

    D3D11_TEXTURE1D_DESC Tex1DDesc = 
    {
        m_Desc.Width,
        m_Desc.MipLevels,
        m_Desc.ArraySize,
        D3D11TexFormat,
        D3D11Usage,
        D3D11BindFlags,
        D3D11CPUAccessFlags,
        MiscFlags
    };

    std::vector<D3D11_SUBRESOURCE_DATA, STDAllocatorRawMem<D3D11_SUBRESOURCE_DATA>> D3D11InitData( STD_ALLOCATOR_RAW_MEM(D3D11_SUBRESOURCE_DATA, GetRawAllocator(), "Allocator for vector<D3D11_SUBRESOURCE_DATA>") );
    PrepareD3D11InitData(InitData, Tex1DDesc.ArraySize * Tex1DDesc.MipLevels, D3D11InitData);

    ID3D11Texture1D *ptex1D = nullptr;
    HRESULT hr = pDeviceD3D11->CreateTexture1D(&Tex1DDesc, D3D11InitData.size() ? D3D11InitData.data() : nullptr, &ptex1D);
    m_pd3d11Texture.Attach(ptex1D);
    CHECK_D3D_RESULT_THROW( hr, "Failed to create the Direct3D11 Texture1D" );
}
CommandListManager::CommandListManager(RenderDeviceD3D12Impl *pDeviceD3D12) : 
    m_pDeviceD3D12(pDeviceD3D12),
    m_DiscardedAllocators(STD_ALLOCATOR_RAW_MEM(DiscardedAllocatorQueueElemType, GetRawAllocator(), "Allocator for deque<DiscardedAllocatorQueueElemType>"))
{
}
/// \param [in] CreationAttribs - Engine creation attributes.
/// \param [out] ppDevice - Address of the memory location where pointer to 
///                         the created device will be written.
/// \param [out] ppImmediateContext - Address of the memory location where pointers to 
///                                   the immediate context will be written.
/// \param [in] SCDesc - Swap chain description.
/// \param [out] ppSwapChain    - Address of the memory location where pointer to the new 
///                               swap chain will be written.
void EngineFactoryOpenGLImpl::CreateDeviceAndSwapChainGL(const EngineGLAttribs& CreationAttribs,
                                                         IRenderDevice **ppDevice,
                                                         IDeviceContext **ppImmediateContext,
                                                         const SwapChainDesc& SCDesc, 
                                                         ISwapChain **ppSwapChain )
{
    if (CreationAttribs.DebugMessageCallback != nullptr)
        SetDebugMessageCallback(CreationAttribs.DebugMessageCallback);

    VERIFY( ppDevice && ppImmediateContext && ppSwapChain, "Null pointer provided" );
    if( !ppDevice || !ppImmediateContext || !ppSwapChain )
        return;

    *ppDevice = nullptr;
    *ppImmediateContext = nullptr;
    *ppSwapChain = nullptr;

    try
    {
        SetRawAllocator(CreationAttribs.pRawMemAllocator);
        auto &RawMemAllocator = GetRawAllocator();

        RenderDeviceGLImpl *pRenderDeviceOpenGL( NEW_RC_OBJ(RawMemAllocator, "TRenderDeviceGLImpl instance", TRenderDeviceGLImpl)(RawMemAllocator, CreationAttribs) );
        pRenderDeviceOpenGL->QueryInterface(IID_RenderDevice, reinterpret_cast<IObject**>(ppDevice) );

        DeviceContextGLImpl *pDeviceContextOpenGL( NEW_RC_OBJ(RawMemAllocator, "DeviceContextGLImpl instance", DeviceContextGLImpl)(pRenderDeviceOpenGL, false ) );
        // We must call AddRef() (implicitly through QueryInterface()) because pRenderDeviceOpenGL will
        // keep a weak reference to the context
        pDeviceContextOpenGL->QueryInterface(IID_DeviceContext, reinterpret_cast<IObject**>(ppImmediateContext) );
        pRenderDeviceOpenGL->SetImmediateContext(pDeviceContextOpenGL);

        TSwapChain *pSwapChainGL = NEW_RC_OBJ(RawMemAllocator, "SwapChainGLImpl instance", TSwapChain)(CreationAttribs, SCDesc, pRenderDeviceOpenGL, pDeviceContextOpenGL );
        pSwapChainGL->QueryInterface(IID_SwapChain, reinterpret_cast<IObject**>(ppSwapChain) );

        pDeviceContextOpenGL->SetSwapChain(pSwapChainGL);
        // Bind default framebuffer and viewport
        pDeviceContextOpenGL->SetRenderTargets( 0, nullptr, nullptr );
        pDeviceContextOpenGL->SetViewports( 1, nullptr, 0, 0 );
    }
    catch( const std::runtime_error & )
    {
        if( *ppDevice )
        {
            (*ppDevice)->Release();
            *ppDevice = nullptr;
        }

        if( *ppImmediateContext )
        {
            (*ppImmediateContext)->Release();
            *ppImmediateContext = nullptr;
        }

        if( *ppSwapChain )
        {
            (*ppSwapChain)->Release();
            *ppSwapChain = nullptr;
        }

        LOG_ERROR( "Failed to initialize OpenGL-based render device" );
    }
}
void EngineFactoryOpenGLImpl::CreateHLSL2GLSLConverter(IHLSL2GLSLConverter **ppConverter)
{
    HLSL2GLSLConverterObject *pConverter( NEW_RC_OBJ(GetRawAllocator(), "HLSL2GLSLConverterObject instance", HLSL2GLSLConverterObject)() );
    pConverter->QueryInterface( IID_HLSL2GLSLConverter, reinterpret_cast<IObject**>(ppConverter) );
}