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" );
}
void BufferD3D11Impl::CreateSRV( struct BufferViewDesc &SRVDesc, ID3D11ShaderResourceView **ppD3D11SRV )
{
    CorrectBufferViewDesc( SRVDesc );

    D3D11_SHADER_RESOURCE_VIEW_DESC D3D11_SRVDesc;
    BufferViewDesc_to_D3D11_SRV_DESC(m_Desc, SRVDesc, D3D11_SRVDesc);

    auto *pDeviceD3D11 = static_cast<RenderDeviceD3D11Impl*>(GetDevice())->GetD3D11Device();
    CHECK_D3D_RESULT_THROW( pDeviceD3D11->CreateShaderResourceView( m_pd3d11Buffer, &D3D11_SRVDesc, ppD3D11SRV ),
                            "Failed to create D3D11 shader resource view" );
}
void BufferD3D11Impl::CreateUAV( BufferViewDesc &UAVDesc, ID3D11UnorderedAccessView **ppD3D11UAV )
{
    CorrectBufferViewDesc( UAVDesc );

    D3D11_UNORDERED_ACCESS_VIEW_DESC D3D11_UAVDesc;
    BufferViewDesc_to_D3D11_UAV_DESC(m_Desc, UAVDesc, D3D11_UAVDesc);

    auto *pDeviceD3D11 = static_cast<RenderDeviceD3D11Impl*>(GetDevice())->GetD3D11Device();
    CHECK_D3D_RESULT_THROW( pDeviceD3D11->CreateUnorderedAccessView( m_pd3d11Buffer, &D3D11_UAVDesc, ppD3D11UAV ),
                            "Failed to create D3D11 unordered access view" );
}
ShaderD3DBase::ShaderD3DBase(const ShaderCreationAttribs &CreationAttribs)
{
    std::string strShaderProfile;
    switch(CreationAttribs.Desc.ShaderType)
    {
        case SHADER_TYPE_VERTEX:  strShaderProfile="vs"; break;
        case SHADER_TYPE_PIXEL:   strShaderProfile="ps"; break;
        case SHADER_TYPE_GEOMETRY:strShaderProfile="gs"; break;
        case SHADER_TYPE_HULL:    strShaderProfile="hs"; break;
        case SHADER_TYPE_DOMAIN:  strShaderProfile="ds"; break;
        case SHADER_TYPE_COMPUTE: strShaderProfile="cs"; break;

        default: UNEXPECTED( "Unknown shader type" );
    }
    strShaderProfile += "_";
    auto *pProfileSuffix = DXShaderProfileToString(CreationAttribs.Desc.TargetProfile);
    strShaderProfile += pProfileSuffix;

    String ShaderSource(g_HLSLDefinitions);
    if( CreationAttribs.Source )
        ShaderSource.append( CreationAttribs.Source );
    else
    {
        VERIFY(CreationAttribs.pShaderSourceStreamFactory, "Input stream factory is null");
        VERIFY(CreationAttribs.FilePath, "File path is null. Either shader source or source file path must be specified.");
        RefCntAutoPtr<IFileStream> pSourceStream;
        CreationAttribs.pShaderSourceStreamFactory->CreateInputStream( CreationAttribs.FilePath, &pSourceStream );
        RefCntAutoPtr<Diligent::IDataBlob> pFileData( new Diligent::DataBlobImpl );
        pSourceStream->Read( pFileData );
        // Null terminator is not read from the stream!
        auto* FileDataPtr = reinterpret_cast<Char*>( pFileData->GetDataPtr() );
        auto Size = pFileData->GetSize();
        ShaderSource.append( FileDataPtr, FileDataPtr + Size/sizeof(*FileDataPtr) );
    }

    const D3D_SHADER_MACRO *pDefines = nullptr;
    std::vector<D3D_SHADER_MACRO> D3DMacros;
    if( CreationAttribs.Macros )
    {
        for( auto* pCurrMacro = CreationAttribs.Macros; pCurrMacro->Name && pCurrMacro->Definition; ++pCurrMacro )
        {
            D3DMacros.push_back( {pCurrMacro->Name, pCurrMacro->Definition} );
        }
        D3DMacros.push_back( {nullptr, nullptr} );
        pDefines = D3DMacros.data();
    }

    CHECK_D3D_RESULT_THROW( CompileShader( ShaderSource.c_str(), CreationAttribs.EntryPoint, pDefines, CreationAttribs.pShaderSourceStreamFactory, strShaderProfile.c_str(), &m_pShaderByteCode ),
                            "Failed to compile the shader");
}
GenerateMipsHelper::GenerateMipsHelper(ID3D12Device *pd3d12Device)
{
    CD3DX12_ROOT_PARAMETER Params[3];
    Params[0].InitAsConstants(4, 0);
    CD3DX12_DESCRIPTOR_RANGE SRVRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0);
    Params[1].InitAsDescriptorTable(1, &SRVRange);
    CD3DX12_DESCRIPTOR_RANGE UAVRange(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 4, 0);
    Params[2].InitAsDescriptorTable(1, &UAVRange);
    CD3DX12_STATIC_SAMPLER_DESC SamplerLinearClampDesc(
        0, D3D12_FILTER_MIN_MAG_MIP_LINEAR, D3D12_TEXTURE_ADDRESS_MODE_CLAMP, D3D12_TEXTURE_ADDRESS_MODE_CLAMP, D3D12_TEXTURE_ADDRESS_MODE_CLAMP);
    CD3DX12_ROOT_SIGNATURE_DESC RootSigDesc;
    RootSigDesc.NumParameters = _countof(Params);
    RootSigDesc.pParameters = Params;
    RootSigDesc.NumStaticSamplers = 1;
    RootSigDesc.pStaticSamplers = &SamplerLinearClampDesc;
    RootSigDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE;

    CComPtr<ID3DBlob> signature;
    CComPtr<ID3DBlob> error;
    HRESULT hr = D3D12SerializeRootSignature(&RootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error);
    hr = pd3d12Device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), __uuidof(m_pGenerateMipsRS), reinterpret_cast<void**>( static_cast<ID3D12RootSignature**>(&m_pGenerateMipsRS)));
    CHECK_D3D_RESULT_THROW(hr, "Failed to create root signature for mipmap generation")

    D3D12_COMPUTE_PIPELINE_STATE_DESC PSODesc = {};
    PSODesc.pRootSignature = m_pGenerateMipsRS;
    PSODesc.NodeMask = 0;
    PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE;

#define CreatePSO(PSO, ShaderByteCode) \
        PSODesc.CS.pShaderBytecode = ShaderByteCode;\
        PSODesc.CS.BytecodeLength = sizeof(ShaderByteCode);\
        hr = pd3d12Device->CreateComputePipelineState(&PSODesc, __uuidof(PSO), reinterpret_cast<void**>( static_cast<ID3D12PipelineState**>(&PSO))); \
        CHECK_D3D_RESULT_THROW(hr, "Failed to create Pipeline state for mipmap generation")

    CreatePSO(m_pGenerateMipsLinearPSO[0], g_pGenerateMipsLinearCS);
    CreatePSO(m_pGenerateMipsLinearPSO[1], g_pGenerateMipsLinearOddXCS);
    CreatePSO(m_pGenerateMipsLinearPSO[2], g_pGenerateMipsLinearOddYCS);
    CreatePSO(m_pGenerateMipsLinearPSO[3], g_pGenerateMipsLinearOddCS);
    CreatePSO(m_pGenerateMipsGammaPSO[0], g_pGenerateMipsGammaCS);
    CreatePSO(m_pGenerateMipsGammaPSO[1], g_pGenerateMipsGammaOddXCS);
    CreatePSO(m_pGenerateMipsGammaPSO[2], g_pGenerateMipsGammaOddYCS);
    CreatePSO(m_pGenerateMipsGammaPSO[3], g_pGenerateMipsGammaOddCS);
}
void Texture1D_D3D11::CreateUAV( TextureViewDesc &UAVDesc, ID3D11UnorderedAccessView **ppD3D11UAV )
{
    VERIFY( ppD3D11UAV && *ppD3D11UAV == nullptr, "UAV pointer address is null or contains non-null pointer to an existing object"  );

    VERIFY( UAVDesc.ViewType == TEXTURE_VIEW_UNORDERED_ACCESS, "Incorrect view type: unordered access is expected" );
    if( !(UAVDesc.TextureDim == RESOURCE_DIM_TEX_1D || UAVDesc.TextureDim == RESOURCE_DIM_TEX_1D_ARRAY) )
        LOG_ERROR_AND_THROW("Unsupported texture type. Only RESOURCE_DIM_TEX_1D or RESOURCE_DIM_TEX_1D_ARRAY is allowed");
    
    if( UAVDesc.Format == TEX_FORMAT_UNKNOWN )
    {
        UAVDesc.Format = m_Desc.Format;
    }

    D3D11_UNORDERED_ACCESS_VIEW_DESC D3D11_UAVDesc;
    TextureViewDesc_to_D3D11_UAV_DESC(UAVDesc, D3D11_UAVDesc);

    auto *pDeviceD3D11 = static_cast<RenderDeviceD3D11Impl*>(GetDevice())->GetD3D11Device();
    CHECK_D3D_RESULT_THROW( pDeviceD3D11->CreateUnorderedAccessView( m_pd3d11Texture, &D3D11_UAVDesc, ppD3D11UAV ),
                            "Failed to create D3D11 unordered access view");
}
void Texture1D_D3D11::CreateDSV( TextureViewDesc &DSVDesc, ID3D11DepthStencilView  **ppD3D11DSV )
{
    VERIFY( ppD3D11DSV && *ppD3D11DSV == nullptr, "DSV pointer address is null or contains non-null pointer to an existing object"  );

    VERIFY( DSVDesc.ViewType == TEXTURE_VIEW_DEPTH_STENCIL, "Incorrect view type: depth stencil is expected" );
    if( !(DSVDesc.TextureDim == RESOURCE_DIM_TEX_1D || DSVDesc.TextureDim == RESOURCE_DIM_TEX_1D_ARRAY) )
        LOG_ERROR_AND_THROW("Unsupported texture type. Only RESOURCE_DIM_TEX_1D or RESOURCE_DIM_TEX_1D_ARRAY is allowed");

    if( DSVDesc.Format == TEX_FORMAT_UNKNOWN )
    {
        DSVDesc.Format = m_Desc.Format;
    }

    D3D11_DEPTH_STENCIL_VIEW_DESC D3D11_DSVDesc;
    TextureViewDesc_to_D3D11_DSV_DESC(DSVDesc, D3D11_DSVDesc, m_Desc.SampleCount);

    auto *pDeviceD3D11 = static_cast<RenderDeviceD3D11Impl*>(GetDevice())->GetD3D11Device();
    CHECK_D3D_RESULT_THROW( pDeviceD3D11->CreateDepthStencilView( m_pd3d11Texture, &D3D11_DSVDesc, ppD3D11DSV ),
                            "Failed to create D3D11 depth stencil view");
}
void Texture1D_D3D11::CreateRTV( TextureViewDesc &RTVDesc, ID3D11RenderTargetView **ppD3D11RTV )
{
    VERIFY( ppD3D11RTV && *ppD3D11RTV == nullptr, "RTV pointer address is null or contains non-null pointer to an existing object" );
    
    VERIFY( RTVDesc.ViewType == TEXTURE_VIEW_RENDER_TARGET, "Incorrect view type: render target is expected" );
    if( !(RTVDesc.TextureDim == RESOURCE_DIM_TEX_1D || RTVDesc.TextureDim == RESOURCE_DIM_TEX_1D_ARRAY ) )
        LOG_ERROR_AND_THROW( "Unsupported texture type. Only RESOURCE_DIM_TEX_1D or RESOURCE_DIM_TEX_1D_ARRAY is allowed" );

    if( RTVDesc.Format == TEX_FORMAT_UNKNOWN )
    {
        RTVDesc.Format = m_Desc.Format;
    }

    D3D11_RENDER_TARGET_VIEW_DESC D3D11_RTVDesc;
    TextureViewDesc_to_D3D11_RTV_DESC(RTVDesc, D3D11_RTVDesc, m_Desc.SampleCount);

    auto *pDeviceD3D11 = static_cast<RenderDeviceD3D11Impl*>(GetDevice())->GetD3D11Device();
    CHECK_D3D_RESULT_THROW( pDeviceD3D11->CreateRenderTargetView( m_pd3d11Texture, &D3D11_RTVDesc, ppD3D11RTV ),
                            "Failed to create D3D11 render target view");
}
void Texture1D_D3D11::CreateSRV( TextureViewDesc &SRVDesc, ID3D11ShaderResourceView **ppD3D11SRV )
{
    VERIFY( ppD3D11SRV && *ppD3D11SRV == nullptr, "SRV pointer address is null or contains non-null pointer to an existing object" );
    
    VERIFY( SRVDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE, "Incorrect view type: shader resource is expected" );
    if( !(SRVDesc.TextureDim == RESOURCE_DIM_TEX_1D || SRVDesc.TextureDim == RESOURCE_DIM_TEX_1D_ARRAY) )
        LOG_ERROR_AND_THROW( "Unsupported texture type. Only RESOURCE_DIM_TEX_1D or RESOURCE_DIM_TEX_1D_ARRAY is allowed" );
    
    if( SRVDesc.Format == TEX_FORMAT_UNKNOWN )
    {
        SRVDesc.Format = m_Desc.Format;
    }

    D3D11_SHADER_RESOURCE_VIEW_DESC D3D11_SRVDesc;
    TextureViewDesc_to_D3D11_SRV_DESC(SRVDesc, D3D11_SRVDesc, m_Desc.SampleCount);

    auto *pDeviceD3D11 = static_cast<RenderDeviceD3D11Impl*>(GetDevice())->GetD3D11Device();
    CHECK_D3D_RESULT_THROW( pDeviceD3D11->CreateShaderResourceView( m_pd3d11Texture, &D3D11_SRVDesc, ppD3D11SRV ),
                            "Failed to create D3D11 shader resource view");
}