/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   2009?/X/X - 2016/12/06
/// 
/// @brief  DirectX  バッファ基本操作等。
/// 
/// ****************************************************************************

#pragma once

#include "CPL_DX_Layout_Buffer.h"
#include "CPL_DX_AutoMap.h"
#include "CPL_DX_Exception.h"

namespace CPL {
namespace DX {
namespace Buffer {


const int PIPELINE_SET_MAX_NUM = 4;

// テンプレートマルチタイプ化の簡易定義用マクロ
#define CPL_DX_BUFFER_DEF_TEMPLATE_IDX( new_class_name, base_class_name )\
  template<int ID>\
  class new_class_name : public base_class_name {\
  public:\
    using base_class_name::base_class_name;\
  }


// _____________________________________________________________________________
/// @brief バッファデータ
///
// *****************************************************************************
class BaseBuffer_
  : public Interface_
{
  friend class Pipeline;
protected:
  mutable CpDXBuffer m_cp_dx_buffer;
  size_t             m_element_size;
  size_t             m_element_num;
  //UINT               m_type_ID;
  int                m_slot_No;
  Core::SStringA<64> m_buf_name; // 最大63文字
  Pipeline::Function M_Pipeline[ PIPELINE_SET_MAX_NUM+1 ];
  
  HRESULT   zzf_SetData
              ( D3D11_MAP in_flag_map
              , size_t    in_index
              , void_cptr in_ptr_data
              , size_t    in_element_num = 1
              );
  HRESULT   zzf_GetData
              ( size_t    in_index
              , void_ptr  out_ptr_data
              , size_t    in_element_num = 1
              ) const;
  HRESULT   zzf_Map
              ( D3D11_MAP in_flag_map
              , void_ptr* io_pp_buf
              , UINT      in_subresource = 0
              );
  HRESULT   zzf_Map
              ( void_cptr* out_pp_buf
              , UINT       in_subresource = 0
              ) const;

  // 
  BaseBuffer_( _in<int> in_slot_No );

  // バッファ作成付きコンストラクタ
  template<class T_DerivedClass>
  BaseBuffer_
  ( T_DerivedClass* in_ptr_this
  , _in<size_t>     in_element_size
  , _in<size_t>     in_element_num
  , pin<void  >     in_ptr_init_data
  , _in<UINT  >     in_slot_No_default
  ) : m_buf_name("")
  {
    new( in_ptr_this ) T_DerivedClass( InitializeVT_() ); // 仮想関数テーブルのみ設定するため呼び出し
    memset( M_Pipeline, 0, sizeof(M_Pipeline) );
    HRESULT hr = Create( in_element_size, in_element_num, in_ptr_init_data );
    CPL_THROW_IF( FAILED(hr), "Filed to Create Buffer." );
  }

public:
  // _____________________________________________________________________________
  /// @brief 初期化指定コンストラクタ 
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  BaseBuffer_( _in<InitializeVT_> ivt ) : m_buf_name("") {}
  
  // _____________________________________________________________________________
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  HRESULT Create
            ( _in<size_t> in_element_size
            , _in<size_t> in_element_num
            , pin<void  > in_ptr_init_data
            );
  // _____________________________________________________________________________
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  void    Release();
  // _____________________________________________________________________________
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  void    Unmap();

  // _____________________________________________________________________________
  /// @brief 要素サイズの取得
  /// 
  /// @return 要素サイズを返します。
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  size_t  GetElementSize() const { return m_element_size; }

  // _____________________________________________________________________________
  /// @brief 要素数の取得
  /// 
  /// @return 要素数を返します。
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  size_t  GetElementNum()  const { return m_element_num; }

  // _____________________________________________________________________________
  /// @brief バッファ全体のサイズの取得
  /// 
  /// @return バッファ全体のサイズを返します。
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  size_t  GetSize() const { return m_element_size * m_element_num; }

  // _____________________________________________________________________________
  /// @brief バッファ名の取得
  /// 
  /// @return バッファ名を返します。
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  cref<Core::SStringA<64>>
          GetName() const { return m_buf_name; }

  // _____________________________________________________________________________
  /// @brief バッファ名の設定
  /// 
  /// @param[in] in_buf_name : バッファ名を指定します。
  /// 
  /// @return なし。
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  void    SetName( pin<char> in_buf_name ){ m_buf_name = in_buf_name; }

  // _____________________________________________________________________________
  /// @brief DirectXバッファ(ID3D11Buffer等)の取得
  /// 
  /// @return DirectXバッファオブジェクトのスマートポインタを返します。
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  cptr<DXBuffer>
          GetDxObject() const { return m_cp_dx_buffer; }
  /// @copydoc GetDxObject
  ptr<DXBuffer>
          GetDxObject()       { return m_cp_dx_buffer; }

  // _____________________________________________________________________________
  /// @brief スロット番号の取得
  /// 
  /// @return 設定しているスロット番号を返します。
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  int     GetSlotNo()   const { return m_slot_No; }

  // _____________________________________________________________________________
  /// @brief スロットNoの設定
  /// 
  /// @param[in] in_slot_No : 使用するスロットNoを指定します。
  /// 
  /// @return なし。
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  void    SetSlotNo( _in<int> in_slot_No ){ m_slot_No = in_slot_No; }

  // _____________________________________________________________________________
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  void    SetPipeline
            ( pin<Pipeline::Function> in_pipeline_function_list
            , _in<int               > in_func_num
            );
  // _____________________________________________________________________________
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  HRESULT RenderSetup( DXDeviceContext* in_ptr_d3d_IC );
};






// _____________________________________________________________________________
/// @brief GPU読み出し専用バッファ ( GPU Read Only )
///
// *****************************************************************************
template<UINT BIND>
class Immutable
  : public BaseBuffer_
{
  friend class BaseBuffer_;
  friend class Immutable;
protected:
  // ↓使用禁止
  HRESULT   SetData( _in<size_t>, pin<void>, _in<size_t> )   override { return E_NOINTERFACE; }
  HRESULT   GetData( _in<size_t>, pout<void>, _in<size_t> ) const override { return E_NOINTERFACE; }
  HRESULT   Map    ( pout<void_ptr>,  _in<UINT> )        override { return E_NOINTERFACE; }
  HRESULT   Map    ( pout<void_cptr>, _in<UINT> )  const override { return E_NOINTERFACE; }
  void      Unmap  () override {}
public:
  D3D11_USAGE GetUsage()            const override { return D3D11_USAGE_IMMUTABLE; }
  UINT        GetBindFlags()        const override { return BIND; }
  UINT        GetCPUAccessFlags()   const override { return 0; }
  UINT        GetMiscFlags()        const override { return 0; }
  UINT        GetSysMemPichi()      const override { return 0; }
  UINT        GetSysMemSlicePitch() const override { return 0; }
  
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // コンストラクタ
  Immutable( _in<int> in_slot_No = -1 )
    : BaseBuffer_( in_slot_No )
  {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // バッファ作成付きコンストラクタ
  // in_slot_No_default - デフォルトでは-1
  // in_slot_No_default==-1ならば、上位で指定される場合はその値が。指定され
  // なければ０が使用される
  Immutable
  ( _in<size_t> in_element_size
  , _in<size_t> in_element_num
  , pin<void  > in_ptr_init_data
  , _in<UINT  > in_slot_No_default = -1
  ) : BaseBuffer_
      ( this
      , in_element_size
      , in_element_num
      , in_ptr_init_data
      , in_slot_No_default
      )
  {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // デストラクタ
  ~Immutable(){}
  
protected:
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // 仮想関数テーブル初期化用コンストラクタ
  Immutable( InitializeVT_ const& ivt ) : BaseBuffer_( ivt ){}

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // 派生クラスからバッファ作成付きコンストラクタ呼び出し用コンストラクタ
  template<class T_DerivedClass>
  Immutable
  ( T_DerivedClass* in_ptr_this
  , _in<size_t>     in_element_size
  , _in<size_t>     in_element_num
  , pin<void  >     in_ptr_init_data
  , _in<UINT  >     in_slot_No_default
  ) : BaseBuffer_
      ( in_ptr_this
      , in_element_size
      , in_element_num
      , in_ptr_init_data
      , in_slot_No_default
      )
  {}
};



typedef Immutable<D3D11_BIND_VERTEX_BUFFER>    Immutable_Vertex;
typedef Immutable<D3D11_BIND_INDEX_BUFFER>     Immutable_Index;
typedef Immutable<D3D11_BIND_CONSTANT_BUFFER>  Immutable_Constant;
typedef Immutable<D3D11_BIND_SHADER_RESOURCE>  Immutable_ShaderResource;

CPL_DX_BUFFER_DEF_TEMPLATE_IDX( Immutable_Vertex_X,         Immutable_Vertex );
CPL_DX_BUFFER_DEF_TEMPLATE_IDX( Immutable_Index_X,          Immutable_Index );
CPL_DX_BUFFER_DEF_TEMPLATE_IDX( Immutable_Constant_X,       Immutable_Constant );
CPL_DX_BUFFER_DEF_TEMPLATE_IDX( Immutable_ShaderResource_X, Immutable_ShaderResource );






// _____________________________________________________________________________
/// @brief GPU読み書き可能バッファ ( GPU Read / GPU Write )
///
// *****************************************************************************
template<UINT BIND>
class Default
  : public BaseBuffer_
{
  friend class BaseBuffer_;
  friend class Default;
protected:
  // ↓使用禁止
  HRESULT   SetData( _in<size_t>, pin<void>,  _in<size_t> ) override { return E_NOINTERFACE; }
  HRESULT   GetData( _in<size_t>, pout<void>, _in<size_t> ) const override { return E_NOINTERFACE; }
  HRESULT   Map    ( pout<void_ptr>,  _in<UINT> )        override { return E_NOINTERFACE; }
  HRESULT   Map    ( pout<void_cptr>, _in<UINT> )  const override { return E_NOINTERFACE; }
  void      Unmap  () override {}
public:
  D3D11_USAGE     GetUsage()            const override { return D3D11_USAGE_DEFAULT; }
  UINT            GetBindFlags()        const override { return BIND; }
  UINT            GetCPUAccessFlags()   const override { return 0; }
  UINT            GetMiscFlags()        const override { return 0; }
  UINT            GetSysMemPichi()      const override { return 0; }
  UINT            GetSysMemSlicePitch() const override { return 0; }

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // コンストラクタ
  Default( _in<UINT> in_slot_No_default = -1 )
    : BaseBuffer_( in_slot_No_default )
  {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // バッファ作成付きコンストラクタ
  Default
  ( _in<size_t> in_element_size
  , _in<size_t> in_element_num
  , pin<void  > in_ptr_init_data
  , _in<UINT  > in_slot_No_default = -1
  ) : BaseBuffer_
      ( this
      , in_element_size
      , in_element_num
      , in_ptr_init_data
      , in_slot_No_default
      )
  {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // デストラクタ
  ~Default(){}
  
protected:
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // 仮想関数テーブル初期化用コンストラクタ
  Default( InitializeVT_ const& ivt ) : BaseBuffer_( ivt ){}
  
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // 継承先から呼び出す、バッファ作成付きコンストラクタ
  template<class T_DerivedClass>
  Default
  ( T_DerivedClass* in_ptr_this
  , _in<size_t> in_element_size
  , _in<size_t> in_element_num
  , pin<void  > in_ptr_init_data
  , _in<UINT  > in_slot_No_default
  ) : BaseBuffer_
      ( in_ptr_this
      , in_element_size
      , in_element_num
      , in_ptr_init_data
      , in_slot_No_default
      )
  {}
};


typedef Default<D3D11_BIND_VERTEX_BUFFER>    Default_Vertex;
typedef Default<D3D11_BIND_INDEX_BUFFER>     Default_Index;
typedef Default<D3D11_BIND_CONSTANT_BUFFER>  Default_Constant;
typedef Default<D3D11_BIND_SHADER_RESOURCE>  Default_ShaderResource;
typedef Default<D3D11_BIND_STREAM_OUTPUT>    Default_StreamOutput;
typedef Default<D3D11_BIND_RENDER_TARGET>    Default_RenderTarget;
typedef Default<D3D11_BIND_DEPTH_STENCIL>    Default_DepthStencil;
typedef Default<D3D11_BIND_UNORDERED_ACCESS> Default_UnOrdered;

CPL_DX_BUFFER_DEF_TEMPLATE_IDX( Default_Vertex_X,         Default_Vertex );
CPL_DX_BUFFER_DEF_TEMPLATE_IDX( Default_Index_X,          Default_Index );
CPL_DX_BUFFER_DEF_TEMPLATE_IDX( Default_Constant_X,       Default_Constant );
CPL_DX_BUFFER_DEF_TEMPLATE_IDX( Default_ShaderResource_X, Default_ShaderResource );
CPL_DX_BUFFER_DEF_TEMPLATE_IDX( Default_StreamOutput_X,   Default_StreamOutput );
CPL_DX_BUFFER_DEF_TEMPLATE_IDX( Default_RenderTarget_X,   Default_RenderTarget );
CPL_DX_BUFFER_DEF_TEMPLATE_IDX( Default_DepthStencil_X,   Default_DepthStencil );
CPL_DX_BUFFER_DEF_TEMPLATE_IDX( Default_UnOrdered_X,      Default_UnOrdered );






// _____________________________________________________________________________
/// @brief 動的バッファ ( CPU Write / GPU Read )
///
// *****************************************************************************
template<UINT BIND>
class Dynamic
  : public BaseBuffer_
{
  friend class BaseBuffer_;
  friend class Dynamic;
protected:
  // ↓使用禁止
  HRESULT   GetData( _in<size_t>, pout<void>, _in<size_t> ) const override { return E_NOINTERFACE; }
  HRESULT   Map    ( pout<void_cptr>, _in<UINT> )      const override { return E_NOINTERFACE; }
public:
  D3D11_USAGE     GetUsage()            const override { return D3D11_USAGE_DYNAMIC; }
  UINT            GetBindFlags()        const override { return BIND; }
  UINT            GetCPUAccessFlags()   const override { return D3D11_CPU_ACCESS_WRITE; }
  UINT            GetMiscFlags()        const override { return 0; }
  UINT            GetSysMemPichi()      const override { return 0; }
  UINT            GetSysMemSlicePitch() const override { return 0; }
  
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // マッピング（書き込み用）
  HRESULT Map( pout<void_ptr> out_pp_buf, _in<UINT> in_subresource = 0 ) override
  {
    return zzf_Map( D3D11_MAP_WRITE_DISCARD, out_pp_buf, in_subresource );
  }
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // データ書き込み
  HRESULT
    SetData
      ( _in<size_t> in_index
      , pin<void  > in_ptr_data
      , _in<size_t> in_element_num = 1
      ) override
  {
    return zzf_SetData
      ( D3D11_MAP_WRITE_DISCARD
      , in_index
      , in_ptr_data
      , in_element_num
      );
  }
  
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // コンストラクタ
  Dynamic( _in<UINT> in_slot_No_default = -1 )
    : BaseBuffer_( in_slot_No_default )
  {}
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // バッファ作成付きコンストラクタ
  Dynamic
  ( _in<size_t> in_element_size
  , _in<size_t> in_element_num
  , pin<void  > in_ptr_init_data
  , _in<UINT  > in_slot_No_default = -1
  ) : BaseBuffer_
      ( this
      , in_element_size
      , in_element_num
      , in_ptr_init_data
      , in_slot_No_default
      )
  {}
  ~Dynamic(){}
  
protected:
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // 仮想関数テーブル初期化用コンストラクタ
  Dynamic( InitializeVT_ const& ivt ) : BaseBuffer_( ivt ){}
  
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // 継承先から呼び出し用のバッファ作成付きコンストラクタ
  template<class T_DerivedClass>
  Dynamic
  ( T_DerivedClass* in_ptr_this
  , _in<size_t> in_element_size
  , _in<size_t> in_element_num
  , pin<void  > in_ptr_init_data
  , _in<UINT  > in_slot_No_default
  ) : BaseBuffer_
      ( in_ptr_this
      , in_element_size
      , in_element_num
      , in_ptr_init_data
      , in_slot_No_default
      )
  {}
};


typedef Dynamic<D3D11_BIND_VERTEX_BUFFER>    Dynamic_Vertex;
typedef Dynamic<D3D11_BIND_INDEX_BUFFER>     Dynamic_Index;
typedef Dynamic<D3D11_BIND_CONSTANT_BUFFER>  Dynamic_Constant;
typedef Dynamic<D3D11_BIND_SHADER_RESOURCE>  Dynamic_ShaderResource;

CPL_DX_BUFFER_DEF_TEMPLATE_IDX( Dynamic_Vertex_X,         Dynamic_Vertex );
CPL_DX_BUFFER_DEF_TEMPLATE_IDX( Dynamic_Index_X,          Dynamic_Index );
CPL_DX_BUFFER_DEF_TEMPLATE_IDX( Dynamic_Constant_X,       Dynamic_Constant );
CPL_DX_BUFFER_DEF_TEMPLATE_IDX( Dynamic_ShaderResource_X, Dynamic_ShaderResource );






// _____________________________________________________________________________
/// @brief 拡張可能バッファ
///
/// メインメモリにデータをバックアップし、バッファの変更・拡張をサポートする。
///
// *****************************************************************************
class DynamicEX
  : public Dynamic<0>
{
  typedef Core::Array::Dynamic<char> TYPE_BUF;

  TYPE_BUF     m_temp_buffer;
  U16          m_flags_bind;
  mutable bool m_flag_change;
  mutable bool m_flag_resize;

protected:
  // 直接使用は非推奨（継承元からのみ呼び出す場合のみ有効とする）
  HRESULT Map( pout<void_cptr> out_pp_buf, _in<UINT> in_subresource = 0 ) const;
  HRESULT Map( pout<void_ptr> out_pp_buf,  _in<UINT> in_subresource = 0 );
  void    Unmap();

public:
  UINT GetBindFlags() const { return m_flags_bind; }

  HRESULT Create
            ( _in<size_t> in_element_size
            , _in<size_t> in_element_num
            , pin<void  > in_ptr_init_data
            );
  void    Release();
  HRESULT SetData
            ( _in<size_t> in_index
            , pin<void  > in_ptr_data
            , _in<size_t> in_element_num = 1
            );
  HRESULT GetData
            ( _in <size_t> in_index
            , pout<void  > out_ptr_data
            , _in <size_t> in_element_num = 1
            ) const;
  HRESULT RenderSetup( DXDeviceContext* in_ptr_d3d_IC );

  // 拡張インターフェイス
  void    Reserve( _in<size_t> in_element_size, _in<size_t> in_element_num );
  void    Resize( _in<size_t> in_element_num );
  bool    Add( _in<size_t> in_index, pin<void> in_ptr_ins_data, _in<size_t> in_insert_byte_size = 0 );
  bool    AddEnd( pin<void> in_ptr_ins_data, _in<size_t> in_insert_byte_size = 0 );
  bool    Delete( _in<size_t> in_index, _in<size_t> in_delete_num = 1 );
  bool    DeleteTable( pin<size_t> in_index_table, _in<size_t> in_table_num );
  void    Updated(){ m_flag_change = true; }

  template<class T, class IDX>
  T const& GetElement( IDX in_element_index, SDEF in_offset_byte = 0 ) const
  {
    return
      *reinterpret_cast<T const*>(
        &m_temp_buffer[ in_element_index * m_element_size + in_offset_byte ]);
  }
  template<class T, class IDX>
  T& GetElement( IDX in_element_index, int in_offset_byte = 0 )
  {
    return
      *reinterpret_cast<T*>(
        &m_temp_buffer[ in_element_index * m_element_size + in_offset_byte ]);
  }

  template<class T>
  void SetElement( size_t in_index, T const& in_data, int in_offset_byte = 0 )
  {
    Updated();
    const int byte_index = in_index * m_element_size + in_offset_byte;
    *static_cast<T const*>(&m_temp_buffer[ byte_index ]) = in_data;
  }
  template<class T>
  void
    SetElement
      ( size_t   in_index
      , T const* in_data
      , int      in_num
      , int      in_offset_byte = 0
      )
  {
    Updated();
    memset
      ( &m_temp_buffer[ in_index * m_element_size + in_offset_byte ]
      , &in_data
      , sizeof(T) * in_num
      );
  }

  // _____________________________________________________________________________
  /// @brief コンストラクタ（バッファ生成なし）
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  DynamicEX( _in<U16> in_flags_bind, _in<UINT> in_slot_No_default = -1 )
    : Dynamic( in_slot_No_default )
    , m_flags_bind( in_flags_bind )
  {}

  DynamicEX
  ( _in<size_t> in_element_size
  , _in<size_t> in_element_num
  , _in<UINT  > in_flags_bind
  , pin<void  > in_ptr_init_data
  , _in<UINT  > in_slot_No_default = -1
  );

  ~DynamicEX();

protected:
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // 仮想関数テーブル初期化用コンストラクタ
  DynamicEX( InitializeVT_ ivt ) : Dynamic( ivt ){}
  
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // 継承先から呼び出し用のバッファ作成付きコンストラクタ
  template<class T_DerivedClass>
  DynamicEX
  ( T_DerivedClass* in_ptr_this
  , size_t          in_element_size
  , size_t          in_element_num
  , UINT            in_flags_bind
  , void_cptr       in_ptr_init_data
  , UINT            in_slot_No_default
  ) : Dynamic
      ( in_ptr_this
      , in_element_size
      , in_element_num
      , in_ptr_init_data
      , in_slot_No_default
      )
  {}
};


/// @cond
namespace zzz_ {
  // =============================================================================
  // バインドタイプ化用クラス
  // =============================================================================
  template<UINT BIND>
  class DynamicEX_Bind
    : public DynamicEX
  {
  public:
    DynamicEX_Bind( _in<UINT> in_slot_No_default = -1 )
      : DynamicEX( BIND, in_slot_No_default )
    {}
    DynamicEX_Bind
    ( _in<size_t> in_element_size
    , _in<size_t> in_element_num
    , pin<void  > in_ptr_init_data
    , _in<UINT  > in_slot_No_default = -1
    ) : DynamicEX
        ( in_element_size
        , in_element_num
        , BIND
        , in_ptr_init_data
        , in_slot_No_default
        )
    {}
  };
} // namespace zzz_
/// @endcond


typedef zzz_::DynamicEX_Bind<D3D11_BIND_VERTEX_BUFFER>    DynamicEX_Vertex;
typedef zzz_::DynamicEX_Bind<D3D11_BIND_INDEX_BUFFER>     DynamicEX_Index;
typedef zzz_::DynamicEX_Bind<D3D11_BIND_CONSTANT_BUFFER>  DynamicEX_Constant;
typedef zzz_::DynamicEX_Bind<D3D11_BIND_SHADER_RESOURCE>  DynamicEX_ShaderResource;

CPL_DX_BUFFER_DEF_TEMPLATE_IDX( DynamicEX_Vertex_X,         DynamicEX_Vertex );
CPL_DX_BUFFER_DEF_TEMPLATE_IDX( DynamicEX_Index_X,          DynamicEX_Index );
CPL_DX_BUFFER_DEF_TEMPLATE_IDX( DynamicEX_Constant_X,       DynamicEX_Constant );
CPL_DX_BUFFER_DEF_TEMPLATE_IDX( DynamicEX_ShaderResource_X, DynamicEX_ShaderResource );





// _____________________________________________________________________________
/// @brief ステージングバッファ ( CPU Read / CPU Write / GPU Read / GPU Write )
///
// *****************************************************************************
template<UINT BIND>
class Staging
  : public BaseBuffer_
{
  friend class BaseBuffer_;
  friend class Staging;
  friend class DynamicEX;
protected:
  CpDXBuffer m_cp_dx_buffer;
public:
  DXBuffer const* GetDxObject() const override { return m_cp_dx_buffer; }
  DXBuffer*       GetDxObject()       override { return m_cp_dx_buffer; }
  D3D11_USAGE     GetUsage()            const override { return D3D11_USAGE_STAGING; }
  UINT            GetBindFlags()        const override { return BIND; }
  UINT            GetCPUAccessFlags()   const override { return D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ; }
  UINT            GetMiscFlags()        const override { return 0; }
  UINT            GetSysMemPichi()      const override { return 0; }
  UINT            GetSysMemSlicePitch() const override { return 0; }
  
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // マッピング（読み込み専用）
  HRESULT Map( pout<void_cptr> out_pp_buf, _in<UINT> in_subresource = 0 ) const override
  {
    return zzf_Map( out_pp_buf, in_subresource );
  }

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // マッピング（読み書き両用）
  HRESULT Map( pout<void_ptr> io_pp_buf, _in<UINT> in_subresource = 0 ) override
  {
    return zzf_Map( D3D11_MAP_READ_WRITE, io_pp_buf, in_subresource );
  }

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // データ書き込み
  HRESULT
    SetData
      ( _in<size_t> in_index
      , pin<void  > in_ptr_data
      , _in<size_t> in_element_num = 1
      ) override
  {
    return zzf_SetData
      ( D3D11_MAP_WRITE
      , in_index
      , in_ptr_data
      , in_element_num
      );
  }

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // データ読み込み
  HRESULT
    GetData
      ( _in <size_t> in_index
      , pout<void  > out_ptr_data
      , _in <size_t> in_element_num = 1
      ) const override
  {
    return zzf_GetData( in_index, out_ptr_data, in_element_num );
  }

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // コンストラクタ
  Staging( _in<UINT> in_slot_No_default = -1 )
    : BaseBuffer_( in_slot_No_default )
  {}

  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // バッファ作成付きコンストラクタ
  Staging
  ( _in<size_t> in_element_size
  , _in<size_t> in_element_num
  , pin<void  > in_ptr_init_data   = nullptr
  , _in<UINT  > in_slot_No_default = -1
  );
  ~Staging(){}

protected:
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // 仮想関数テーブル初期化用コンストラクタ
  Staging( InitializeVT_ const& ivt ) : BaseBuffer_( ivt ){}
  
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  // 継承先から呼び出し用のバッファ作成付きコンストラクタ
  template<class T_DerivedClass>
  Staging
  ( T_DerivedClass* in_ptr_this
  , _in<size_t>     in_element_size
  , _in<size_t>     in_element_num
  , pin<void  >     in_ptr_init_data
  , _in<UINT  >     in_slot_No_default
  ) : BaseBuffer_
      ( in_ptr_this
      , in_element_size
      , in_element_num
      , in_ptr_init_data
      , in_slot_No_default
      )
  {}
};



typedef Staging<D3D11_BIND_VERTEX_BUFFER>    Staging_Vertex;
typedef Staging<D3D11_BIND_INDEX_BUFFER>     Staging_Index;
typedef Staging<D3D11_BIND_CONSTANT_BUFFER>  Staging_Constant;
typedef Staging<D3D11_BIND_SHADER_RESOURCE>  Staging_ShaderResource;
typedef Staging<D3D11_BIND_STREAM_OUTPUT>    Staging_StreamOutput;
typedef Staging<D3D11_BIND_RENDER_TARGET>    Staging_RenderTarget;
typedef Staging<D3D11_BIND_DEPTH_STENCIL>    Staging_DepthStencil;
typedef Staging<D3D11_BIND_UNORDERED_ACCESS> Staging_UnOrdered;

CPL_DX_BUFFER_DEF_TEMPLATE_IDX( Staging_Vertex_X,         Staging_Vertex );
CPL_DX_BUFFER_DEF_TEMPLATE_IDX( Staging_Index_X,          Staging_Index );
CPL_DX_BUFFER_DEF_TEMPLATE_IDX( Staging_Constant_X,       Staging_Constant );
CPL_DX_BUFFER_DEF_TEMPLATE_IDX( Staging_ShaderResource_X, Staging_ShaderResource );
CPL_DX_BUFFER_DEF_TEMPLATE_IDX( Staging_StreamOutput_X,   Staging_StreamOutput );
CPL_DX_BUFFER_DEF_TEMPLATE_IDX( Staging_RenderTarget_X,   Staging_RenderTarget );
CPL_DX_BUFFER_DEF_TEMPLATE_IDX( Staging_DepthStencil_X,   Staging_DepthStencil );
CPL_DX_BUFFER_DEF_TEMPLATE_IDX( Staging_UnOrdered_X,      Staging_UnOrdered );




} // namespace Buffer
} // namespace DX
} // namespace CPL
