/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2019-2023 Baldur Karlsson
 * Copyright (c) 2014 Crytek
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/

#pragma once

#define INITGUID

#include "core/core.h"
#include "driver/dx/official/d3d11_4.h"
#include "driver/dx/official/dxgi1_3.h"
#include "driver/dxgi/dxgi_common.h"
#include "driver/shaders/dxbc/dxbc_compile.h"

class WrappedID3D11Device;
struct D3D11RenderState;

// replay only class for handling marker regions
struct D3D11MarkerRegion
{
  D3D11MarkerRegion(const rdcstr &marker);
  ~D3D11MarkerRegion();
  static void Set(const rdcstr &marker);
  static void Begin(const rdcstr &marker);
  static void End();

  static WrappedID3D11Device *device;
};

struct ResourceRange
{
private:
  enum Empty
  {
    empty
  };

  // used to initialise Null below
  ResourceRange(Empty)
  {
    resource = NULL;
    minMip = 0;
    maxMip = 0;
    minSlice = 0;
    maxSlice = 0;
    fullRange = false;
    depthReadOnly = false;
    stencilReadOnly = false;
  }

public:
  static ResourceRange Null;

  ResourceRange(ID3D11Buffer *res);
  ResourceRange(ID3D11Texture2D *res);

  // construct a range for a specific mip/slice. Used for easily checking if
  // a view includes this mip/slice
  ResourceRange(ID3D11Resource *res, UINT mip, UINT slice);

  // initialises the range with the contents of the view
  ResourceRange(ID3D11ShaderResourceView *srv);
  ResourceRange(ID3D11UnorderedAccessView *uav);
  ResourceRange(ID3D11RenderTargetView *rtv);
  ResourceRange(ID3D11DepthStencilView *dsv);

  bool Intersects(const ResourceRange &range) const
  {
    if(resource != range.resource)
      return false;

    // we are the same resource, but maybe we refer to disjoint
    // ranges of the subresources. Do an early-out check though
    // if either of the ranges refers to the whole resource
    if(fullRange || range.fullRange)
      return true;

    // do we refer to the same mip anywhere
    if(minMip <= range.maxMip && range.minMip <= maxMip)
    {
      // and the same slice? (for resources without slices, this will just be
      // 0 - ~0U so definitely true
      if(minSlice <= range.maxSlice && range.minSlice <= maxSlice)
        return true;
    }

    // if not, then we don't intersect
    return false;
  }

  bool IsDepthReadOnly() const { return depthReadOnly; }
  bool IsStencilReadOnly() const { return stencilReadOnly; }
  bool IsNull() const { return resource == NULL; }
  ID3D11Resource *GetResource() const { return resource; }
  UINT GetMinMip() const { return minMip; }
  UINT GetMaxMip() const { return maxMip; }
  UINT GetMinSlice() const { return minSlice; }
  UINT GetMaxSlice() const { return maxSlice; }
private:
  ResourceRange();

  void SetMaxes(UINT numMips, UINT numSlices)
  {
    if(numMips == allMip)
      maxMip = allMip;
    else
      maxMip = minMip + numMips - 1;

    if(numSlices == allSlice)
      maxSlice = allSlice;
    else
      maxSlice = minSlice + numSlices - 1;

    // save this bool for faster intersection tests. Note that full range could also
    // be true if maxMip == 12 or something, but since this is just a conservative
    // early out we are only concerned with a common case.
    fullRange = (minMip == 0 && minSlice == 0 && maxMip == allMip && maxSlice == allSlice);
  }

  static const UINT allMip = 0xf;
  static const UINT allSlice = 0x7ff;

  ID3D11Resource *resource;
  UINT minMip : 4;
  UINT minSlice : 12;
  UINT maxMip : 4;
  UINT maxSlice : 12;
  UINT fullRange : 1;
  UINT depthReadOnly : 1;
  UINT stencilReadOnly : 1;
};

// don't need to differentiate arrays as we treat everything
// as an array (potentially with only one element).
enum D3D11TextureDetailsType
{
  eTexType_1D = 1,
  eTexType_2D,
  eTexType_3D,
  eTexType_Depth,
  eTexType_Stencil,
  eTexType_DepthMS,
  eTexType_StencilMS,
  eTexType_Unused,    // removed, kept just to keep slots the same
  eTexType_2DMS,
  eTexType_YUV,
  eTexType_Max
};

template <typename T>
inline const ResourceRange &GetResourceRange(T *);

TextureType MakeTextureDim(D3D11_SRV_DIMENSION dim);
TextureType MakeTextureDim(D3D11_RTV_DIMENSION dim);
TextureType MakeTextureDim(D3D11_DSV_DIMENSION dim);
TextureType MakeTextureDim(D3D11_UAV_DIMENSION dim);
AddressMode MakeAddressMode(D3D11_TEXTURE_ADDRESS_MODE addr);
CompareFunction MakeCompareFunc(D3D11_COMPARISON_FUNC func);
TextureFilter MakeFilter(D3D11_FILTER filter);
LogicOperation MakeLogicOp(D3D11_LOGIC_OP op);
BlendMultiplier MakeBlendMultiplier(D3D11_BLEND blend, bool alpha);
BlendOperation MakeBlendOp(D3D11_BLEND_OP op);
StencilOperation MakeStencilOp(D3D11_STENCIL_OP op);

template <class T>
inline void SetDebugName(T *pObj, const char *name)
{
  if(pObj)
    pObj->SetPrivateData(WKPDID_D3DDebugObjectName, name ? (UINT)strlen(name) : 0, name);
}

template <class T>
inline rdcstr GetDebugName(T *pObj)
{
  static const UINT DEBUG_NAME_SIZE = 1024;
  static wchar_t tmpBuf[DEBUG_NAME_SIZE] = {0};    // Used for both char and wchar_t
  if(pObj)
  {
    // Try char first
    UINT size = DEBUG_NAME_SIZE - 1;
    HRESULT hr = pObj->GetPrivateData(WKPDID_D3DDebugObjectName, &size, (char *)tmpBuf);
    if(SUCCEEDED(hr))
    {
      return rdcstr((char *)tmpBuf, size);
    }

    // Try wchar_t
    size = (DEBUG_NAME_SIZE - 1) * sizeof(wchar_t);
    hr = pObj->GetPrivateData(WKPDID_D3DDebugObjectNameW, &size, tmpBuf);
    if(SUCCEEDED(hr))
    {
      size /= 2;    // Convert from bytes read to wide char count
      rdcwstr sName(tmpBuf, size);
      return StringFormat::Wide2UTF8(sName);
    }
  }

  return rdcstr();
}

#define SAFE_INTADDREF(p) \
  do                      \
  {                       \
    if(p)                 \
    {                     \
      IntAddRef(p);       \
    }                     \
  } while((void)0, 0)

#define SAFE_INTRELEASE(p) \
  do                       \
  {                        \
    if(p)                  \
    {                      \
      IntRelease(p);       \
      (p) = NULL;          \
    }                      \
  } while((void)0, 0)

#if ENABLED(RDOC_DEVEL)
#define ASSERT_REFCOUNT(refcount) \
  if(refcount < 0)                \
    RDCERR("Unbalanced refcounting, refcount has dropped below 0");
#else
#define ASSERT_REFCOUNT(refcount)
#endif

#define IMPLEMENT_FUNCTION_SERIALISED(ret, func, ...) \
  ret func(__VA_ARGS__);                              \
  template <typename SerialiserType>                  \
  bool CONCAT(Serialise_, func(SerialiserType &ser, __VA_ARGS__));

#define INSTANTIATE_FUNCTION_SERIALISED(ret, parent, func, ...)                     \
  template bool parent::CONCAT(Serialise_, func(ReadSerialiser &ser, __VA_ARGS__)); \
  template bool parent::CONCAT(Serialise_, func(WriteSerialiser &ser, __VA_ARGS__));

#define USE_SCRATCH_SERIALISER() WriteSerialiser &ser = m_ScratchSerialiser;

#define SERIALISE_TIME_CALL(...)                                          \
  m_ScratchSerialiser.ChunkMetadata().timestampMicro = Timing::GetTick(); \
  __VA_ARGS__;                                                            \
  m_ScratchSerialiser.ChunkMetadata().durationMicro =                     \
      Timing::GetTick() - m_ScratchSerialiser.ChunkMetadata().timestampMicro;

// A handy macros to say "is the serialiser reading and we're doing replay-mode stuff?"
// The reason we check both is that checking the first allows the compiler to eliminate the other
// path at compile-time, and the second because we might be just struct-serialising in which case we
// should be doing no work to restore states.
// Writing is unambiguously during capture mode, so we don't have to check both in that case.
#define IsReplayingAndReading() (ser.IsReading() && IsReplayMode(m_State))

enum class D3D11Chunk : uint32_t
{
  DeviceInitialisation = (uint32_t)SystemChunk::FirstDriverChunk,
  SetResourceName,
  CreateSwapBuffer,
  CreateTexture1D,
  CreateTexture2D,
  CreateTexture3D,
  CreateBuffer,
  CreateVertexShader,
  CreateHullShader,
  CreateDomainShader,
  CreateGeometryShader,
  CreateGeometryShaderWithStreamOutput,
  CreatePixelShader,
  CreateComputeShader,
  GetClassInstance,
  CreateClassInstance,
  CreateClassLinkage,
  CreateShaderResourceView,
  CreateRenderTargetView,
  CreateDepthStencilView,
  CreateUnorderedAccessView,
  CreateInputLayout,
  CreateBlendState,
  CreateDepthStencilState,
  CreateRasterizerState,
  CreateSamplerState,
  CreateQuery,
  CreatePredicate,
  CreateCounter,
  CreateDeferredContext,
  SetExceptionMode,
  OpenSharedResource,
  IASetInputLayout,
  IASetVertexBuffers,
  IASetIndexBuffer,
  IASetPrimitiveTopology,
  VSSetConstantBuffers,
  VSSetShaderResources,
  VSSetSamplers,
  VSSetShader,
  HSSetConstantBuffers,
  HSSetShaderResources,
  HSSetSamplers,
  HSSetShader,
  DSSetConstantBuffers,
  DSSetShaderResources,
  DSSetSamplers,
  DSSetShader,
  GSSetConstantBuffers,
  GSSetShaderResources,
  GSSetSamplers,
  GSSetShader,
  SOSetTargets,
  PSSetConstantBuffers,
  PSSetShaderResources,
  PSSetSamplers,
  PSSetShader,
  CSSetConstantBuffers,
  CSSetShaderResources,
  CSSetUnorderedAccessViews,
  CSSetSamplers,
  CSSetShader,
  RSSetViewports,
  RSSetScissorRects,
  RSSetState,
  OMSetRenderTargets,
  OMSetRenderTargetsAndUnorderedAccessViews,
  OMSetBlendState,
  OMSetDepthStencilState,
  DrawIndexedInstanced,
  DrawInstanced,
  DrawIndexed,
  Draw,
  DrawAuto,
  DrawIndexedInstancedIndirect,
  DrawInstancedIndirect,
  Map,
  Unmap,
  CopySubresourceRegion,
  CopyResource,
  UpdateSubresource,
  CopyStructureCount,
  ResolveSubresource,
  GenerateMips,
  ClearDepthStencilView,
  ClearRenderTargetView,
  ClearUnorderedAccessViewUint,
  ClearUnorderedAccessViewFloat,
  ClearState,
  ExecuteCommandList,
  Dispatch,
  DispatchIndirect,
  FinishCommandList,
  Flush,
  SetPredication,
  SetResourceMinLOD,
  Begin,
  End,
  CreateRasterizerState1,
  CreateBlendState1,
  CopySubresourceRegion1,
  UpdateSubresource1,
  ClearView,
  VSSetConstantBuffers1,
  HSSetConstantBuffers1,
  DSSetConstantBuffers1,
  GSSetConstantBuffers1,
  PSSetConstantBuffers1,
  CSSetConstantBuffers1,
  PushMarker,
  SetMarker,
  PopMarker,
  SetShaderDebugPath,
  DiscardResource,
  DiscardView,
  DiscardView1,
  CreateRasterizerState2,
  CreateQuery1,
  CreateTexture2D1,
  CreateTexture3D1,
  CreateShaderResourceView1,
  CreateRenderTargetView1,
  CreateUnorderedAccessView1,
  SwapchainPresent,
  PostExecuteCommandList,
  PostFinishCommandListSet,
  SwapDeviceContextState,
  ExternalDXGIResource,
  OpenSharedResource1,
  OpenSharedResourceByName,
  SetShaderExtUAV,
  Max,
};

DECLARE_REFLECTION_ENUM(D3D11Chunk);

// this is special - these serialise overloads will fetch the ID during capture, serialise the ID
// directly as-if it were the original type, then on replay load up the resource if available.
// Really this is only one type of serialisation, but we declare a couple of overloads to account
// for resources being accessed through different interfaces in different functions
#define SERIALISE_D3D_INTERFACES()                \
  SERIALISE_INTERFACE(ID3D11DeviceChild);         \
  SERIALISE_INTERFACE(ID3D11Resource);            \
  SERIALISE_INTERFACE(ID3D11View);                \
  SERIALISE_INTERFACE(ID3D11UnorderedAccessView); \
  SERIALISE_INTERFACE(ID3D11ShaderResourceView);  \
  SERIALISE_INTERFACE(ID3D11RenderTargetView);    \
  SERIALISE_INTERFACE(ID3D11DepthStencilView);    \
  SERIALISE_INTERFACE(ID3D11BlendState);          \
  SERIALISE_INTERFACE(ID3D11DepthStencilState);   \
  SERIALISE_INTERFACE(ID3D11RasterizerState);     \
  SERIALISE_INTERFACE(ID3D11SamplerState);        \
  SERIALISE_INTERFACE(ID3D11Buffer);              \
  SERIALISE_INTERFACE(ID3D11ClassInstance);       \
  SERIALISE_INTERFACE(ID3D11ClassLinkage);        \
  SERIALISE_INTERFACE(ID3D11InputLayout);         \
  SERIALISE_INTERFACE(ID3D11VertexShader);        \
  SERIALISE_INTERFACE(ID3D11HullShader);          \
  SERIALISE_INTERFACE(ID3D11DomainShader);        \
  SERIALISE_INTERFACE(ID3D11GeometryShader);      \
  SERIALISE_INTERFACE(ID3D11PixelShader);         \
  SERIALISE_INTERFACE(ID3D11ComputeShader);       \
  SERIALISE_INTERFACE(ID3D11CommandList);         \
  SERIALISE_INTERFACE(ID3D11Counter);             \
  SERIALISE_INTERFACE(ID3D11Predicate);           \
  SERIALISE_INTERFACE(ID3D11Query);               \
  SERIALISE_INTERFACE(ID3D11Asynchronous);

#define SERIALISE_INTERFACE(iface) DECLARE_REFLECTION_STRUCT(iface *)

SERIALISE_D3D_INTERFACES();

DECLARE_REFLECTION_ENUM(D3D11_BIND_FLAG);
DECLARE_REFLECTION_ENUM(D3D11_CPU_ACCESS_FLAG);
DECLARE_REFLECTION_ENUM(D3D11_RESOURCE_MISC_FLAG);
DECLARE_REFLECTION_ENUM(D3D11_COLOR_WRITE_ENABLE);
DECLARE_REFLECTION_ENUM(D3D11_BUFFER_UAV_FLAG);
DECLARE_REFLECTION_ENUM(D3D11_DSV_FLAG);
DECLARE_REFLECTION_ENUM(D3D11_COPY_FLAGS);
DECLARE_REFLECTION_ENUM(D3D11_MAP_FLAG);
DECLARE_REFLECTION_ENUM(D3D11_CLEAR_FLAG);
DECLARE_REFLECTION_ENUM(D3D11_BUFFEREX_SRV_FLAG);
DECLARE_REFLECTION_ENUM(D3D11_TEXTURE_LAYOUT);
DECLARE_REFLECTION_ENUM(D3D11_DEPTH_WRITE_MASK);
DECLARE_REFLECTION_ENUM(D3D11_COMPARISON_FUNC);
DECLARE_REFLECTION_ENUM(D3D11_STENCIL_OP);
DECLARE_REFLECTION_ENUM(D3D11_BLEND);
DECLARE_REFLECTION_ENUM(D3D11_BLEND_OP);
DECLARE_REFLECTION_ENUM(D3D11_CULL_MODE);
DECLARE_REFLECTION_ENUM(D3D11_FILL_MODE);
DECLARE_REFLECTION_ENUM(D3D11_CONSERVATIVE_RASTERIZATION_MODE);
DECLARE_REFLECTION_ENUM(D3D11_TEXTURE_ADDRESS_MODE);
DECLARE_REFLECTION_ENUM(D3D11_FILTER);
DECLARE_REFLECTION_ENUM(D3D11_SRV_DIMENSION);
DECLARE_REFLECTION_ENUM(D3D11_RTV_DIMENSION);
DECLARE_REFLECTION_ENUM(D3D11_UAV_DIMENSION);
DECLARE_REFLECTION_ENUM(D3D11_DSV_DIMENSION);
DECLARE_REFLECTION_ENUM(D3D11_CONTEXT_TYPE);
DECLARE_REFLECTION_ENUM(D3D11_QUERY);
DECLARE_REFLECTION_ENUM(D3D11_COUNTER);
DECLARE_REFLECTION_ENUM(D3D11_MAP);
DECLARE_REFLECTION_ENUM(D3D11_PRIMITIVE_TOPOLOGY);
DECLARE_REFLECTION_ENUM(D3D11_USAGE);
DECLARE_REFLECTION_ENUM(D3D11_INPUT_CLASSIFICATION);
DECLARE_REFLECTION_ENUM(D3D11_LOGIC_OP);

// declare reflect-able types

DECLARE_REFLECTION_STRUCT(D3D11_BUFFER_DESC);
DECLARE_REFLECTION_STRUCT(D3D11_TEXTURE1D_DESC);
DECLARE_REFLECTION_STRUCT(D3D11_TEXTURE2D_DESC);
DECLARE_REFLECTION_STRUCT(D3D11_TEXTURE2D_DESC1);
DECLARE_REFLECTION_STRUCT(D3D11_TEXTURE3D_DESC);
DECLARE_REFLECTION_STRUCT(D3D11_TEXTURE3D_DESC1);
DECLARE_REFLECTION_STRUCT(D3D11_BUFFER_SRV);
DECLARE_REFLECTION_STRUCT(D3D11_BUFFEREX_SRV);
DECLARE_REFLECTION_STRUCT(D3D11_TEX1D_SRV);
DECLARE_REFLECTION_STRUCT(D3D11_TEX1D_ARRAY_SRV);
DECLARE_REFLECTION_STRUCT(D3D11_TEX2D_SRV);
DECLARE_REFLECTION_STRUCT(D3D11_TEX2D_ARRAY_SRV);
DECLARE_REFLECTION_STRUCT(D3D11_TEX2D_SRV1);
DECLARE_REFLECTION_STRUCT(D3D11_TEX2D_ARRAY_SRV1);
DECLARE_REFLECTION_STRUCT(D3D11_TEX3D_SRV);
DECLARE_REFLECTION_STRUCT(D3D11_TEXCUBE_SRV);
DECLARE_REFLECTION_STRUCT(D3D11_TEXCUBE_ARRAY_SRV);
DECLARE_REFLECTION_STRUCT(D3D11_TEX2DMS_SRV);
DECLARE_REFLECTION_STRUCT(D3D11_TEX2DMS_ARRAY_SRV);
DECLARE_REFLECTION_STRUCT(D3D11_SHADER_RESOURCE_VIEW_DESC);
DECLARE_REFLECTION_STRUCT(D3D11_SHADER_RESOURCE_VIEW_DESC1);
DECLARE_REFLECTION_STRUCT(D3D11_BUFFER_RTV);
DECLARE_REFLECTION_STRUCT(D3D11_TEX1D_RTV);
DECLARE_REFLECTION_STRUCT(D3D11_TEX1D_ARRAY_RTV);
DECLARE_REFLECTION_STRUCT(D3D11_TEX2D_RTV);
DECLARE_REFLECTION_STRUCT(D3D11_TEX2D_ARRAY_RTV);
DECLARE_REFLECTION_STRUCT(D3D11_TEX2DMS_RTV);
DECLARE_REFLECTION_STRUCT(D3D11_TEX2DMS_ARRAY_RTV);
DECLARE_REFLECTION_STRUCT(D3D11_TEX2D_RTV1);
DECLARE_REFLECTION_STRUCT(D3D11_TEX2D_ARRAY_RTV1);
DECLARE_REFLECTION_STRUCT(D3D11_TEX3D_RTV);
DECLARE_REFLECTION_STRUCT(D3D11_RENDER_TARGET_VIEW_DESC);
DECLARE_REFLECTION_STRUCT(D3D11_RENDER_TARGET_VIEW_DESC1);
DECLARE_REFLECTION_STRUCT(D3D11_BUFFER_UAV);
DECLARE_REFLECTION_STRUCT(D3D11_TEX1D_UAV);
DECLARE_REFLECTION_STRUCT(D3D11_TEX1D_ARRAY_UAV);
DECLARE_REFLECTION_STRUCT(D3D11_TEX2D_UAV);
DECLARE_REFLECTION_STRUCT(D3D11_TEX2D_ARRAY_UAV);
DECLARE_REFLECTION_STRUCT(D3D11_TEX2D_UAV1);
DECLARE_REFLECTION_STRUCT(D3D11_TEX2D_ARRAY_UAV1);
DECLARE_REFLECTION_STRUCT(D3D11_TEX3D_UAV);
DECLARE_REFLECTION_STRUCT(D3D11_UNORDERED_ACCESS_VIEW_DESC);
DECLARE_REFLECTION_STRUCT(D3D11_UNORDERED_ACCESS_VIEW_DESC1);
DECLARE_REFLECTION_STRUCT(D3D11_TEX1D_DSV);
DECLARE_REFLECTION_STRUCT(D3D11_TEX1D_ARRAY_DSV);
DECLARE_REFLECTION_STRUCT(D3D11_TEX2D_DSV);
DECLARE_REFLECTION_STRUCT(D3D11_TEX2D_ARRAY_DSV);
DECLARE_REFLECTION_STRUCT(D3D11_TEX2DMS_DSV);
DECLARE_REFLECTION_STRUCT(D3D11_TEX2DMS_ARRAY_DSV);
DECLARE_REFLECTION_STRUCT(D3D11_DEPTH_STENCIL_VIEW_DESC);
DECLARE_REFLECTION_STRUCT(D3D11_RENDER_TARGET_BLEND_DESC);
DECLARE_REFLECTION_STRUCT(D3D11_RENDER_TARGET_BLEND_DESC1);
DECLARE_REFLECTION_STRUCT(D3D11_BLEND_DESC);
DECLARE_REFLECTION_STRUCT(D3D11_BLEND_DESC1);
DECLARE_REFLECTION_STRUCT(D3D11_DEPTH_STENCILOP_DESC);
DECLARE_REFLECTION_STRUCT(D3D11_DEPTH_STENCIL_DESC);
DECLARE_REFLECTION_STRUCT(D3D11_RASTERIZER_DESC);
DECLARE_REFLECTION_STRUCT(D3D11_RASTERIZER_DESC1);
DECLARE_REFLECTION_STRUCT(D3D11_RASTERIZER_DESC2);
DECLARE_REFLECTION_STRUCT(D3D11_QUERY_DESC);
DECLARE_REFLECTION_STRUCT(D3D11_QUERY_DESC1);
DECLARE_REFLECTION_STRUCT(D3D11_COUNTER_DESC);
DECLARE_REFLECTION_STRUCT(D3D11_SAMPLER_DESC);
DECLARE_REFLECTION_STRUCT(D3D11_SO_DECLARATION_ENTRY);
DECLARE_REFLECTION_STRUCT(D3D11_INPUT_ELEMENT_DESC);
DECLARE_REFLECTION_STRUCT(D3D11_SUBRESOURCE_DATA);
DECLARE_REFLECTION_STRUCT(D3D11_VIEWPORT);
DECLARE_REFLECTION_STRUCT(D3D11_RECT);
DECLARE_REFLECTION_STRUCT(D3D11_BOX);
