code:
#pragma once

#include <mutex>
#include <vector>

#include "../dxbc/dxbc_options.h"

#include "../dxgi/dxgi_object.h"
#include "../dxgi/dxgi_interfaces.h"

#include "../dxvk/dxvk_cs.h"

#include "../d3d10/d3d10_device.h"

#include "../util/com/com_private_data.h"

#include "d3d11_cmdlist.h"
#include "d3d11_cuda.h"
#include "d3d11_initializer.h"
#include "d3d11_interfaces.h"
#include "d3d11_interop.h"
#include "d3d11_options.h"
#include "d3d11_shader.h"
#include "d3d11_state.h"
#include "d3d11_util.h"

namespace dxvk {
  class DxgiAdapter;

  class D3D11Buffer;
  class D3D11CommonShader;
  class D3D11CommonTexture;
  class D3D11Counter;
  class D3D11DeviceContext;
  class D3D11DXGIDevice;
  class D3D11ImmediateContext;
  class D3D11Predicate;
  class D3D11Query;
  class D3D11Texture1D;
  class D3D11Texture2D;
  class D3D11Texture3D;

  /**
   * \brief D3D11 device implementation
   *
   * Implements the ID3D11Device interfaces
   * as part of a \ref D3D11DeviceContainer.
   */
  class D3D11Device final : public ID3D11Device5 {
    /// Maximum number of resource init commands per command buffer
    constexpr static uint64_t InitCommandThreshold = 50;
  public:

    D3D11Device(
            D3D11DXGIDevice*        pContainer,
            D3D_FEATURE_LEVEL       FeatureLevel,
            UINT                    FeatureFlags);

    ~D3D11Device();

    ULONG STDMETHODCALLTYPE AddRef();

    ULONG STDMETHODCALLTYPE Release();

    HRESULT STDMETHODCALLTYPE QueryInterface(
            REFIID                  riid,
            void**                  ppvObject);

    HRESULT STDMETHODCALLTYPE CreateBuffer(
      const D3D11_BUFFER_DESC*      pDesc,
      const D3D11_SUBRESOURCE_DATA* pInitialData,
            ID3D11Buffer**          ppBuffer);

    HRESULT STDMETHODCALLTYPE CreateTexture1D(
      const D3D11_TEXTURE1D_DESC*   pDesc,
      const D3D11_SUBRESOURCE_DATA* pInitialData,
            ID3D11Texture1D**       ppTexture1D);

    HRESULT STDMETHODCALLTYPE CreateTexture2D(
      const D3D11_TEXTURE2D_DESC*   pDesc,
      const D3D11_SUBRESOURCE_DATA* pInitialData,
            ID3D11Texture2D**       ppTexture2D);

    HRESULT STDMETHODCALLTYPE CreateTexture2D1(
      const D3D11_TEXTURE2D_DESC1*  pDesc,
      const D3D11_SUBRESOURCE_DATA* pInitialData,
            ID3D11Texture2D1**      ppTexture2D);

    HRESULT STDMETHODCALLTYPE CreateTexture3D(
      const D3D11_TEXTURE3D_DESC*   pDesc,
      const D3D11_SUBRESOURCE_DATA* pInitialData,
            ID3D11Texture3D**       ppTexture3D);

    HRESULT STDMETHODCALLTYPE CreateTexture3D1(
      const D3D11_TEXTURE3D_DESC1*  pDesc,
      const D3D11_SUBRESOURCE_DATA* pInitialData,
            ID3D11Texture3D1**      ppTexture3D);

    HRESULT STDMETHODCALLTYPE CreateShaderResourceView(
            ID3D11Resource*                   pResource,
      const D3D11_SHADER_RESOURCE_VIEW_DESC*  pDesc,
            ID3D11ShaderResourceView**        ppSRView);

    HRESULT STDMETHODCALLTYPE CreateShaderResourceView1(
            ID3D11Resource*                   pResource,
      const D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc,
            ID3D11ShaderResourceView1**       ppSRView);

    HRESULT STDMETHODCALLTYPE CreateUnorderedAccessView(
            ID3D11Resource*                   pResource,
      const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc,
            ID3D11UnorderedAccessView**       ppUAView);

    HRESULT STDMETHODCALLTYPE CreateUnorderedAccessView1(
            ID3D11Resource*                   pResource,
      const D3D11_UNORDERED_ACCESS_VIEW_DESC1* pDesc,
            ID3D11UnorderedAccessView1**      ppUAView);

    HRESULT STDMETHODCALLTYPE CreateRenderTargetView(
            ID3D11Resource*                   pResource,
      const D3D11_RENDER_TARGET_VIEW_DESC*    pDesc,
            ID3D11RenderTargetView**          ppRTView);

    HRESULT STDMETHODCALLTYPE CreateRenderTargetView1(
            ID3D11Resource*                   pResource,
      const D3D11_RENDER_TARGET_VIEW_DESC1*   pDesc,
            ID3D11RenderTargetView1**         ppRTView);

    HRESULT STDMETHODCALLTYPE CreateDepthStencilView(
            ID3D11Resource*                   pResource,
      const D3D11_DEPTH_STENCIL_VIEW_DESC*    pDesc,
            ID3D11DepthStencilView**          ppDepthStencilView);

    HRESULT STDMETHODCALLTYPE CreateInputLayout(
      const D3D11_INPUT_ELEMENT_DESC*   pInputElementDescs,
            UINT                        NumElements,
      const void*                       pShaderBytecodeWithInputSignature,
            SIZE_T                      BytecodeLength,
            ID3D11InputLayout**         ppInputLayout);

    HRESULT STDMETHODCALLTYPE CreateVertexShader(
      const void*                       pShaderBytecode,
            SIZE_T                      BytecodeLength,
            ID3D11ClassLinkage*         pClassLinkage,
            ID3D11VertexShader**        ppVertexShader);

    HRESULT STDMETHODCALLTYPE CreateGeometryShader(
      const void*                       pShaderBytecode,
            SIZE_T                      BytecodeLength,
            ID3D11ClassLinkage*         pClassLinkage,
            ID3D11GeometryShader**      ppGeometryShader);

    HRESULT STDMETHODCALLTYPE CreateGeometryShaderWithStreamOutput(
      const void*                       pShaderBytecode,
            SIZE_T                      BytecodeLength,
      const D3D11_SO_DECLARATION_ENTRY* pSODeclaration,
            UINT                        NumEntries,
      const UINT*                       pBufferStrides,
            UINT                        NumStrides,
            UINT                        RasterizedStream,
            ID3D11ClassLinkage*         pClassLinkage,
            ID3D11GeometryShader**      ppGeometryShader);

    HRESULT STDMETHODCALLTYPE CreatePixelShader(
      const void*                       pShaderBytecode,
            SIZE_T                      BytecodeLength,
            ID3D11ClassLinkage*         pClassLinkage,
            ID3D11PixelShader**         ppPixelShader);

    HRESULT STDMETHODCALLTYPE CreateHullShader(
      const void*                       pShaderBytecode,
            SIZE_T                      BytecodeLength,
            ID3D11ClassLinkage*         pClassLinkage,
            ID3D11HullShader**          ppHullShader);

    HRESULT STDMETHODCALLTYPE CreateDomainShader(
      const void*                       pShaderBytecode,
            SIZE_T                      BytecodeLength,
            ID3D11ClassLinkage*         pClassLinkage,
            ID3D11DomainShader**        ppDomainShader);

    HRESULT STDMETHODCALLTYPE CreateComputeShader(
      const void*                       pShaderBytecode,
            SIZE_T                      BytecodeLength,
            ID3D11ClassLinkage*         pClassLinkage,
            ID3D11ComputeShader**       ppComputeShader);

    HRESULT STDMETHODCALLTYPE CreateClassLinkage(
            ID3D11ClassLinkage**        ppLinkage);

    HRESULT STDMETHODCALLTYPE CreateBlendState(
      const D3D11_BLEND_DESC*           pBlendStateDesc,
            ID3D11BlendState**          ppBlendState);

    HRESULT STDMETHODCALLTYPE CreateBlendState1(
      const D3D11_BLEND_DESC1*          pBlendStateDesc,
            ID3D11BlendState1**         ppBlendState);

    HRESULT STDMETHODCALLTYPE CreateDepthStencilState(
      const D3D11_DEPTH_STENCIL_DESC*   pDepthStencilDesc,
            ID3D11DepthStencilState**   ppDepthStencilState);

    HRESULT STDMETHODCALLTYPE CreateRasterizerState(
      const D3D11_RASTERIZER_DESC*      pRasterizerDesc,
            ID3D11RasterizerState**     ppRasterizerState);

    HRESULT STDMETHODCALLTYPE CreateRasterizerState1(
      const D3D11_RASTERIZER_DESC1*     pRasterizerDesc,
            ID3D11RasterizerState1**    ppRasterizerState);

    HRESULT STDMETHODCALLTYPE CreateRasterizerState2(
      const D3D11_RASTERIZER_DESC2*     pRasterizerDesc,
            ID3D11RasterizerState2**    ppRasterizerState);

    HRESULT STDMETHODCALLTYPE CreateSamplerState(
      const D3D11_SAMPLER_DESC*         pSamplerDesc,
            ID3D11SamplerState**        ppSamplerState);

    HRESULT STDMETHODCALLTYPE CreateQuery(
      const D3D11_QUERY_DESC*           pQueryDesc,
            ID3D11Query**               ppQuery);

    HRESULT STDMETHODCALLTYPE CreateQuery1(
      const D3D11_QUERY_DESC1*          pQueryDesc,
            ID3D11Query1**              ppQuery);

    HRESULT STDMETHODCALLTYPE CreatePredicate(
      const D3D11_QUERY_DESC*           pPredicateDesc,
            ID3D11Predicate**           ppPredicate);

    HRESULT STDMETHODCALLTYPE CreateCounter(
      const D3D11_COUNTER_DESC*         pCounterDesc,
            ID3D11Counter**             ppCounter);

    HRESULT STDMETHODCALLTYPE CreateDeferredContext(
            UINT                        ContextFlags,
            ID3D11DeviceContext**       ppDeferredContext);

    HRESULT STDMETHODCALLTYPE CreateDeferredContext1(
            UINT                        ContextFlags,
            ID3D11DeviceContext1**      ppDeferredContext);

    HRESULT STDMETHODCALLTYPE CreateDeferredContext2(
            UINT                        ContextFlags,
            ID3D11DeviceContext2**      ppDeferredContext);

    HRESULT STDMETHODCALLTYPE CreateDeferredContext3(
            UINT                        ContextFlags,
            ID3D11DeviceContext3**      ppDeferredContext);

    HRESULT STDMETHODCALLTYPE CreateDeviceContextState(
            UINT                        Flags,
      const D3D_FEATURE_LEVEL*          pFeatureLevels,
            UINT                        FeatureLevels,
            UINT                        SDKVersion,
            REFIID                      EmulatedInterface,
            D3D_FEATURE_LEVEL*          pChosenFeatureLevel,
            ID3DDeviceContextState**    ppContextState);

    HRESULT STDMETHODCALLTYPE CreateFence(
            UINT64                      InitialValue,
            D3D11_FENCE_FLAG            Flags,
            REFIID                      riid,
            void**                      ppFence);

    void STDMETHODCALLTYPE ReadFromSubresource(
            void*                       pDstData,
            UINT                        DstRowPitch,
            UINT                        DstDepthPitch,
            ID3D11Resource*             pSrcResource,
            UINT                        SrcSubresource,
      const D3D11_BOX*                  pSrcBox);

    void STDMETHODCALLTYPE WriteToSubresource(
            ID3D11Resource*             pDstResource,
            UINT                        DstSubresource,
      const D3D11_BOX*                  pDstBox,
      const void*                       pSrcData,
            UINT                        SrcRowPitch,
            UINT                        SrcDepthPitch);

    HRESULT STDMETHODCALLTYPE OpenSharedResource(
            HANDLE      hResource,
            REFIID      ReturnedInterface,
            void**      ppResource);

    HRESULT STDMETHODCALLTYPE OpenSharedResource1(
            HANDLE      hResource,
            REFIID      returnedInterface,
            void**      ppResource);

    HRESULT STDMETHODCALLTYPE OpenSharedResourceByName(
            LPCWSTR     lpName,
            DWORD       dwDesiredAccess,
            REFIID      returnedInterface,
            void**      ppResource);

    HRESULT STDMETHODCALLTYPE OpenSharedFence(
            HANDLE      hFence,
            REFIID      ReturnedInterface,
            void**      ppFence);

    HRESULT STDMETHODCALLTYPE CheckFormatSupport(
            DXGI_FORMAT Format,
            UINT*       pFormatSupport);

    HRESULT STDMETHODCALLTYPE CheckMultisampleQualityLevels(
            DXGI_FORMAT Format,
            UINT        SampleCount,
            UINT*       pNumQualityLevels);

    HRESULT STDMETHODCALLTYPE CheckMultisampleQualityLevels1(
            DXGI_FORMAT Format,
            UINT        SampleCount,
            UINT        Flags,
            UINT*       pNumQualityLevels);

    void STDMETHODCALLTYPE CheckCounterInfo(
            D3D11_COUNTER_INFO* pCounterInfo);

    HRESULT STDMETHODCALLTYPE CheckCounter(
      const D3D11_COUNTER_DESC* pDesc,
            D3D11_COUNTER_TYPE* pType,
            UINT*               pActiveCounters,
            LPSTR               szName,
            UINT*               pNameLength,
            LPSTR               szUnits,
            UINT*               pUnitsLength,
            LPSTR               szDescription,
            UINT*               pDescriptionLength);

    HRESULT STDMETHODCALLTYPE CheckFeatureSupport(
            D3D11_FEATURE Feature,
            void*         pFeatureSupportData,
            UINT          FeatureSupportDataSize);

    HRESULT STDMETHODCALLTYPE GetPrivateData(
            REFGUID Name,
            UINT    *pDataSize,
            void    *pData);

    HRESULT STDMETHODCALLTYPE SetPrivateData(
            REFGUID Name,
            UINT    DataSize,
      const void    *pData);

    HRESULT STDMETHODCALLTYPE SetPrivateDataInterface(
            REFGUID  Name,
      const IUnknown *pUnknown);

    D3D_FEATURE_LEVEL STDMETHODCALLTYPE GetFeatureLevel();

    UINT STDMETHODCALLTYPE GetCreationFlags();

    HRESULT STDMETHODCALLTYPE GetDeviceRemovedReason();

    void STDMETHODCALLTYPE GetImmediateContext(
            ID3D11DeviceContext** ppImmediateContext);

    void STDMETHODCALLTYPE GetImmediateContext1(
            ID3D11DeviceContext1** ppImmediateContext);

    void STDMETHODCALLTYPE GetImmediateContext2(
            ID3D11DeviceContext2** ppImmediateContext);

    void STDMETHODCALLTYPE GetImmediateContext3(
            ID3D11DeviceContext3** ppImmediateContext);

    HRESULT STDMETHODCALLTYPE SetExceptionMode(UINT RaiseFlags);

    UINT STDMETHODCALLTYPE GetExceptionMode();

    void STDMETHODCALLTYPE GetResourceTiling(
            ID3D11Resource*           pTiledResource,
            UINT*                     pNumTilesForEntireResource,
            D3D11_PACKED_MIP_DESC*    pPackedMipDesc,
            D3D11_TILE_SHAPE*         pStandardTileShapeForNonPackedMips,
            UINT*                     pNumSubresourceTilings,
            UINT                      FirstSubresourceTilingToGet,
            D3D11_SUBRESOURCE_TILING* pSubresourceTilingsForNonPackedMips);

    HRESULT STDMETHODCALLTYPE RegisterDeviceRemovedEvent(
            HANDLE                    hEvent,
            DWORD*                    pdwCookie);

    void STDMETHODCALLTYPE UnregisterDeviceRemoved(
            DWORD                     dwCookie);

    Rc<DxvkDevice> GetDXVKDevice() {
      return m_dxvkDevice;
    }

    void FlushInitContext();

    VkPipelineStageFlags GetEnabledShaderStages() const {
      return m_dxvkDevice->getShaderPipelineStages();
    }

    DXGI_VK_FORMAT_INFO LookupFormat(
            DXGI_FORMAT           Format,
            DXGI_VK_FORMAT_MODE   Mode) const;

    DXGI_VK_FORMAT_INFO LookupPackedFormat(
            DXGI_FORMAT           Format,
            DXGI_VK_FORMAT_MODE   Mode) const;

    DXGI_VK_FORMAT_FAMILY LookupFamily(
            DXGI_FORMAT           Format,
            DXGI_VK_FORMAT_MODE   Mode) const;

    DxvkCsChunkRef AllocCsChunk(DxvkCsChunkFlags flags) {
      DxvkCsChunk* chunk = m_csChunkPool.allocChunk(flags);
      return DxvkCsChunkRef(chunk, &m_csChunkPool);
    }

    const D3D11Options* GetOptions() const {
      return &m_d3d11Options;
    }

    D3D10Device* GetD3D10Interface() const {
      return m_d3d10Device;
    }

    static bool CheckFeatureLevelSupport(
      const Rc<DxvkInstance>& instance,
      const Rc<DxvkAdapter>&  adapter,
            D3D_FEATURE_LEVEL featureLevel);

    static DxvkDeviceFeatures GetDeviceFeatures(
      const Rc<DxvkAdapter>&  adapter,
            D3D_FEATURE_LEVEL featureLevel);

  private:

    IDXGIObject*                    m_container;

    D3D_FEATURE_LEVEL               m_featureLevel;
    UINT                            m_featureFlags;

    const Rc<DxvkDevice>            m_dxvkDevice;
    const Rc<DxvkAdapter>           m_dxvkAdapter;

    const DXGIVkFormatTable         m_d3d11Formats;
    const D3D11Options              m_d3d11Options;
    const DxbcOptions               m_dxbcOptions;

    DxvkCsChunkPool                 m_csChunkPool;

    D3D11Initializer*               m_initializer = nullptr;
    D3D10Device*                    m_d3d10Device = nullptr;
    Com<D3D11ImmediateContext, false> m_context;

    D3D11StateObjectSet<D3D11BlendState>        m_bsStateObjects;
    D3D11StateObjectSet<D3D11DepthStencilState> m_dsStateObjects;
    D3D11StateObjectSet<D3D11RasterizerState>   m_rsStateObjects;
    D3D11StateObjectSet<D3D11SamplerState>      m_samplerObjects;
    D3D11ShaderModuleSet                        m_shaderModules;

    HRESULT CreateShaderModule(
            D3D11CommonShader*      pShaderModule,
            DxvkShaderKey           ShaderKey,
      const void*                   pShaderBytecode,
            size_t                  BytecodeLength,
            ID3D11ClassLinkage*     pClassLinkage,
      const DxbcModuleInfo*         pModuleInfo);

    HRESULT GetFormatSupportFlags(
            DXGI_FORMAT Format,
            UINT*       pFlags1,
            UINT*       pFlags2) const;

    BOOL GetImageTypeSupport(
            VkFormat    Format,
            VkImageType Type) const;

    template<bool IsKmtHandle>
    HRESULT OpenSharedResourceGeneric(
            HANDLE      hResource,
            REFIID      ReturnedInterface,
            void**      ppResource);

    uint32_t GetViewPlaneIndex(
            ID3D11Resource*         pResource,
            DXGI_FORMAT             ViewFormat);

    template<typename Void>
    void CopySubresourceData(
            Void*                       pData,
            UINT                        RowPitch,
            UINT                        DepthPitch,
            ID3D11Resource*             pResource,
            UINT                        Subresource,
      const D3D11_BOX*                  pBox);

    static D3D_FEATURE_LEVEL GetMaxFeatureLevel(
      const Rc<DxvkInstance>&           pInstance);

  };

  /**
   * \brief Extended D3D11 device
   */
  class D3D11DeviceExt : public ID3D11VkExtDevice1 {

  public:

    D3D11DeviceExt(
            D3D11DXGIDevice*        pContainer,
            D3D11Device*            pDevice);

    ULONG STDMETHODCALLTYPE AddRef();

    ULONG STDMETHODCALLTYPE Release();

    HRESULT STDMETHODCALLTYPE QueryInterface(
            REFIID                  riid,
            void**                  ppvObject);

    BOOL STDMETHODCALLTYPE GetExtensionSupport(
            D3D11_VK_EXTENSION      Extension);

    bool STDMETHODCALLTYPE GetCudaTextureObjectNVX(
            uint32_t                srvDriverHandle,
            uint32_t                samplerDriverHandle,
            uint32_t*               pCudaTextureHandle);

    bool STDMETHODCALLTYPE CreateCubinComputeShaderWithNameNVX(
            const void*             pCubin,
            uint32_t                size,
            uint32_t                blockX,
            uint32_t                blockY,
            uint32_t                blockZ,
            const char*             pShaderName,
            IUnknown**              phShader);

    bool STDMETHODCALLTYPE GetResourceHandleGPUVirtualAddressAndSizeNVX(
            void*                   hObject,
            uint64_t*               gpuVAStart,
            uint64_t*               gpuVASize);

     bool STDMETHODCALLTYPE CreateUnorderedAccessViewAndGetDriverHandleNVX(
            ID3D11Resource*                         pResource,
            const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc,
            ID3D11UnorderedAccessView**             ppUAV,
            uint32_t*                               pDriverHandle);

     bool STDMETHODCALLTYPE CreateShaderResourceViewAndGetDriverHandleNVX(
            ID3D11Resource*                        pResource,
            const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc,
            ID3D11ShaderResourceView**             ppSRV,
            uint32_t*                              pDriverHandle);

     bool STDMETHODCALLTYPE CreateSamplerStateAndGetDriverHandleNVX(
            const D3D11_SAMPLER_DESC* pSamplerDesc,
            ID3D11SamplerState**      ppSamplerState,
            uint32_t*                 pDriverHandle);

  private:

    D3D11DXGIDevice* m_container;
    D3D11Device*     m_device;

    void AddSamplerAndHandleNVX(
            ID3D11SamplerState*       pSampler,
            uint32_t                  Handle);

    ID3D11SamplerState* HandleToSamplerNVX(
            uint32_t                  Handle);

    void AddSrvAndHandleNVX(
            ID3D11ShaderResourceView* pSrv,
            uint32_t                  Handle);

    ID3D11ShaderResourceView* HandleToSrvNVX(
            uint32_t                  Handle);

    dxvk::mutex m_mapLock;
    std::unordered_map<uint32_t, ID3D11SamplerState*> m_samplerHandleToPtr;
    std::unordered_map<uint32_t, ID3D11ShaderResourceView*> m_srvHandleToPtr;
  };

  /**
   * \brief D3D11 video device
   */
  class D3D11VideoDevice : public ID3D11VideoDevice {

  public:

    D3D11VideoDevice(
            D3D11DXGIDevice*        pContainer,
            D3D11Device*            pDevice);

    ~D3D11VideoDevice();

    ULONG STDMETHODCALLTYPE AddRef();

    ULONG STDMETHODCALLTYPE Release();

    HRESULT STDMETHODCALLTYPE QueryInterface(
            REFIID                  riid,
            void**                  ppvObject);

    HRESULT STDMETHODCALLTYPE CreateVideoDecoder(
      const D3D11_VIDEO_DECODER_DESC*                     pVideoDesc,
      const D3D11_VIDEO_DECODER_CONFIG*                   pConfig,
            ID3D11VideoDecoder**                          ppDecoder);

    HRESULT STDMETHODCALLTYPE CreateVideoProcessor(
            ID3D11VideoProcessorEnumerator*               pEnum,
            UINT                                          RateConversionIndex,
            ID3D11VideoProcessor**                        ppVideoProcessor);

    HRESULT STDMETHODCALLTYPE CreateAuthenticatedChannel(
            D3D11_AUTHENTICATED_CHANNEL_TYPE              ChannelType,
            ID3D11AuthenticatedChannel**                  ppAuthenticatedChannel);

    HRESULT STDMETHODCALLTYPE CreateCryptoSession(
      const GUID*                                         pCryptoType,
      const GUID*                                         pDecoderProfile,
      const GUID*                                         pKeyExchangeType,
            ID3D11CryptoSession**                         ppCryptoSession);

    HRESULT STDMETHODCALLTYPE CreateVideoDecoderOutputView(
            ID3D11Resource*                               pResource,
      const D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC*         pDesc,
            ID3D11VideoDecoderOutputView**                ppVDOVView);

    HRESULT STDMETHODCALLTYPE CreateVideoProcessorInputView(
            ID3D11Resource*                               pResource,
            ID3D11VideoProcessorEnumerator*               pEnum,
      const D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC*        pDesc,
            ID3D11VideoProcessorInputView**               ppVPIView);

    HRESULT STDMETHODCALLTYPE CreateVideoProcessorOutputView(
            ID3D11Resource*                               pResource,
            ID3D11VideoProcessorEnumerator*               pEnum,
      const D3D11_VIDEO_PROCESSOR_OUTPUT_VIEW_DESC*       pDesc,
            ID3D11VideoProcessorOutputView**              ppVPOView);

    HRESULT STDMETHODCALLTYPE CreateVideoProcessorEnumerator(
      const D3D11_VIDEO_PROCESSOR_CONTENT_DESC*           pDesc,
            ID3D11VideoProcessorEnumerator**              ppEnum);

    UINT STDMETHODCALLTYPE GetVideoDecoderProfileCount();

    HRESULT STDMETHODCALLTYPE GetVideoDecoderProfile(
            UINT                                          Index,
            GUID*                                         pDecoderProfile);

    HRESULT STDMETHODCALLTYPE CheckVideoDecoderFormat(
      const GUID*                                         pDecoderProfile,
            DXGI_FORMAT                                   Format,
            BOOL*                                         pSupported);

    HRESULT STDMETHODCALLTYPE GetVideoDecoderConfigCount(
      const D3D11_VIDEO_DECODER_DESC*                     pDesc,
            UINT*                                         pCount);

    HRESULT STDMETHODCALLTYPE GetVideoDecoderConfig(
      const D3D11_VIDEO_DECODER_DESC*                     pDesc,
            UINT                                          Index,
            D3D11_VIDEO_DECODER_CONFIG*                   pConfig);

    HRESULT STDMETHODCALLTYPE GetContentProtectionCaps(
      const GUID*                                         pCryptoType,
      const GUID*                                         pDecoderProfile,
            D3D11_VIDEO_CONTENT_PROTECTION_CAPS*          pCaps);

    HRESULT STDMETHODCALLTYPE CheckCryptoKeyExchange(
      const GUID*                                         pCryptoType,
      const GUID*                                         pDecoderProfile,
            UINT                                          Index,
            GUID*                                         pKeyExchangeType);

    HRESULT STDMETHODCALLTYPE SetPrivateData(
            REFGUID                                       Name,
            UINT                                          DataSize,
      const void*                                         pData);

    HRESULT STDMETHODCALLTYPE SetPrivateDataInterface(
            REFGUID                                       Name,
      const IUnknown*                                     pData);

  private:

    D3D11DXGIDevice* m_container;
    D3D11Device*     m_device;

  };

  /**
   * \brief DXGI swap chain factory
   */
  class WineDXGISwapChainFactory : public IWineDXGISwapChainFactory {

  public:

    WineDXGISwapChainFactory(
            D3D11DXGIDevice*        pContainer,
            D3D11Device*            pDevice);

    ULONG STDMETHODCALLTYPE AddRef();

    ULONG STDMETHODCALLTYPE Release();

    HRESULT STDMETHODCALLTYPE QueryInterface(
            REFIID                  riid,
            void**                  ppvObject);

    HRESULT STDMETHODCALLTYPE CreateSwapChainForHwnd(
            IDXGIFactory*           pFactory,
            HWND                    hWnd,
      const DXGI_SWAP_CHAIN_DESC1*  pDesc,
      const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc,
            IDXGIOutput*            pRestrictToOutput,
            IDXGISwapChain1**       ppSwapChain);

  private:

    D3D11DXGIDevice* m_container;
    D3D11Device*     m_device;

  };

  /**
   * \brief D3D11 device metadata shenanigans
   */
  class DXGIDXVKDevice : public IDXGIDXVKDevice {

  public:

    DXGIDXVKDevice(D3D11DXGIDevice* pContainer);

    ULONG STDMETHODCALLTYPE AddRef();

    ULONG STDMETHODCALLTYPE Release();

    HRESULT STDMETHODCALLTYPE QueryInterface(
            REFIID                  riid,
            void**                  ppvObject);

    void STDMETHODCALLTYPE SetAPIVersion(
              UINT                    Version);

    UINT STDMETHODCALLTYPE GetAPIVersion();

  private:

    D3D11DXGIDevice* m_container;
    UINT             m_apiVersion;

  };

  /**
   * \brief D3D11 device container
   *
   * Stores all the objects that contribute to the D3D11
   * device implementation, including the DXGI device.
   */
  class D3D11DXGIDevice : public DxgiObject<IDXGIDevice4> {
    constexpr static uint32_t DefaultFrameLatency = 3;
  public:

    D3D11DXGIDevice(
            IDXGIAdapter*       pAdapter,
      const Rc<DxvkInstance>&   pDxvkInstance,
      const Rc<DxvkAdapter>&    pDxvkAdapter,
            D3D_FEATURE_LEVEL   FeatureLevel,
            UINT                FeatureFlags);

    ~D3D11DXGIDevice();

    HRESULT STDMETHODCALLTYPE QueryInterface(
            REFIID                riid,
            void**                ppvObject);

    HRESULT STDMETHODCALLTYPE GetParent(
            REFIID                riid,
            void**                ppParent);

    HRESULT STDMETHODCALLTYPE CreateSurface(
      const DXGI_SURFACE_DESC*    pDesc,
            UINT                  NumSurfaces,
            DXGI_USAGE            Usage,
      const DXGI_SHARED_RESOURCE* pSharedResource,
            IDXGISurface**        ppSurface) final;

    HRESULT STDMETHODCALLTYPE GetAdapter(
            IDXGIAdapter**        pAdapter) final;

    HRESULT STDMETHODCALLTYPE GetGPUThreadPriority(
            INT*                  pPriority) final;

    HRESULT STDMETHODCALLTYPE QueryResourceResidency(
            IUnknown* const*      ppResources,
            DXGI_RESIDENCY*       pResidencyStatus,
            UINT                  NumResources) final;

    HRESULT STDMETHODCALLTYPE SetGPUThreadPriority(
            INT                   Priority) final;

    HRESULT STDMETHODCALLTYPE GetMaximumFrameLatency(
            UINT*                 pMaxLatency) final;

    HRESULT STDMETHODCALLTYPE SetMaximumFrameLatency(
            UINT                  MaxLatency) final;

    HRESULT STDMETHODCALLTYPE OfferResources(
            UINT                          NumResources,
            IDXGIResource* const*         ppResources,
            DXGI_OFFER_RESOURCE_PRIORITY  Priority) final;

    HRESULT STDMETHODCALLTYPE OfferResources1(
            UINT                          NumResources,
            IDXGIResource* const*         ppResources,
            DXGI_OFFER_RESOURCE_PRIORITY  Priority,
            UINT                          Flags) final;

    HRESULT STDMETHODCALLTYPE ReclaimResources(
            UINT                          NumResources,
            IDXGIResource* const*         ppResources,
            BOOL*                         pDiscarded) final;

    HRESULT STDMETHODCALLTYPE ReclaimResources1(
            UINT                          NumResources,
            IDXGIResource* const*         ppResources,
            DXGI_RECLAIM_RESOURCE_RESULTS* pResults) final;

    HRESULT STDMETHODCALLTYPE EnqueueSetEvent(
            HANDLE                hEvent) final;

    void STDMETHODCALLTYPE Trim() final;

    Rc<DxvkDevice> STDMETHODCALLTYPE GetDXVKDevice();

  private:

    Com<IDXGIAdapter>   m_dxgiAdapter;

    Rc<DxvkInstance>    m_dxvkInstance;
    Rc<DxvkAdapter>     m_dxvkAdapter;
    Rc<DxvkDevice>      m_dxvkDevice;

    D3D11Device         m_d3d11Device;
    D3D11DeviceExt      m_d3d11DeviceExt;
    D3D11VkInterop      m_d3d11Interop;
    D3D11VideoDevice    m_d3d11Video;
    DXGIDXVKDevice      m_metaDevice;

    WineDXGISwapChainFactory m_wineFactory;

    uint32_t m_frameLatency = DefaultFrameLatency;

    Rc<DxvkDevice> CreateDevice(D3D_FEATURE_LEVEL FeatureLevel);

  };

}

repo_name: orochi/dxvk


code:
#pragma once

#include "d3d11_include.h"

#include "../util/com/com_private_data.h"

namespace dxvk {

  class D3D11Device;

  template<typename Base>
  class D3D11DeviceObject : public Base {

  public:

    D3D11DeviceObject(D3D11Device* pDevice)
    : m_parent(pDevice) {

    }

    HRESULT STDMETHODCALLTYPE GetPrivateData(
            REFGUID guid,
            UINT    *pDataSize,
            void    *pData) final {
      return m_privateData.getData(
        guid, pDataSize, pData);
    }

    HRESULT STDMETHODCALLTYPE SetPrivateData(
            REFGUID guid,
            UINT    DataSize,
      const void    *pData) final {
      return m_privateData.setData(
        guid, DataSize, pData);
    }

    HRESULT STDMETHODCALLTYPE SetPrivateDataInterface(
            REFGUID  guid,
      const IUnknown *pUnknown) final {
      return m_privateData.setInterface(
        guid, pUnknown);
    }

    void STDMETHODCALLTYPE GetDevice(
            ID3D11Device**        ppDevice) final {
      *ppDevice = ref(GetParentInterface());
    }

  protected:

    ID3D11Device* GetParentInterface() const {
      // We don't know the definition of ID3D11Device
      // here, because D3D11Device includes this file.
      return reinterpret_cast<ID3D11Device*>(m_parent);
    }

    D3D11Device* const m_parent;

  private:

    ComPrivateData m_privateData;

  };

  template<typename Base>
  class D3D11DeviceChild : public D3D11DeviceObject<ComObject<Base>> {

  public:

    D3D11DeviceChild(D3D11Device* pDevice)
    : D3D11DeviceObject<ComObject<Base>>(pDevice) {

    }

    ULONG STDMETHODCALLTYPE AddRef() {
      uint32_t refCount = this->m_refCount++;
      if (unlikely(!refCount)) {
        this->AddRefPrivate();
        this->GetParentInterface()->AddRef();
      }

      return refCount + 1;
    }

    ULONG STDMETHODCALLTYPE Release() {
      uint32_t refCount = --this->m_refCount;
      if (unlikely(!refCount)) {
        auto* parent = this->GetParentInterface();
        this->ReleasePrivate();
        parent->Release();
      }
      return refCount;
    }

  };

  template<typename Base>
  class D3D11StateObject : public D3D11DeviceObject<Base> {

  public:

    D3D11StateObject(D3D11Device* pDevice)
    : D3D11DeviceObject<Base>(pDevice) {

    }

    ULONG STDMETHODCALLTYPE AddRef() {
      uint32_t refCount = this->m_refCount++;
      if (unlikely(!refCount))
        this->GetParentInterface()->AddRef();

      return refCount + 1;
    }

    ULONG STDMETHODCALLTYPE Release() {
      uint32_t refCount = --this->m_refCount;
      if (unlikely(!refCount))
        this->GetParentInterface()->Release();

      return refCount;
    }

  private:

    std::atomic<uint32_t> m_refCount = { 0u };

  };

}


code:
#include "d3d11_enums.h"

std::ostream& operator << (std::ostream& os, D3D_FEATURE_LEVEL e) {
  switch (e) {
    ENUM_NAME(D3D_FEATURE_LEVEL_9_1);
    ENUM_NAME(D3D_FEATURE_LEVEL_9_2);
    ENUM_NAME(D3D_FEATURE_LEVEL_9_3);
    ENUM_NAME(D3D_FEATURE_LEVEL_10_0);
    ENUM_NAME(D3D_FEATURE_LEVEL_10_1);
    ENUM_NAME(D3D_FEATURE_LEVEL_11_0);
    ENUM_NAME(D3D_FEATURE_LEVEL_11_1);
    ENUM_NAME(D3D_FEATURE_LEVEL_12_0);
    ENUM_NAME(D3D_FEATURE_LEVEL_12_1);
    ENUM_DEFAULT(e);
  }
}


code:
#pragma once

#include <ostream>

#include "d3d11_include.h"

std::ostream& operator << (std::ostream& os, D3D_FEATURE_LEVEL e);


code:
#include "d3d11_fence.h"
#include "d3d11_device.h"

namespace dxvk {

  D3D11Fence::D3D11Fence(
          D3D11Device*        pDevice,
          UINT64              InitialValue,
          D3D11_FENCE_FLAG    Flags,
          HANDLE              hFence)
  : D3D11DeviceChild<ID3D11Fence>(pDevice) {
    DxvkFenceCreateInfo fenceInfo;
    fenceInfo.initialValue = InitialValue;
    m_flags = Flags;

    if (Flags & D3D11_FENCE_FLAG_SHARED) {
      fenceInfo.sharedType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_D3D11_FENCE_BIT;
      if (hFence == nullptr)
        hFence = INVALID_HANDLE_VALUE;
      fenceInfo.sharedHandle = hFence;
    }

    if (Flags & ~D3D11_FENCE_FLAG_SHARED)
      Logger::err(str::format("Fence flags 0x", std::hex, Flags, " not supported"));

    m_fence = pDevice->GetDXVKDevice()->createFence(fenceInfo);
  }

  D3D11Fence::~D3D11Fence() {

  }

  HRESULT STDMETHODCALLTYPE D3D11Fence::QueryInterface(
          REFIID              riid,
          void**              ppvObject) {
    if (ppvObject == nullptr)
      return E_POINTER;

    *ppvObject = nullptr;

    if (riid == __uuidof(IUnknown)
     || riid == __uuidof(ID3D11DeviceChild)
     || riid == __uuidof(ID3D11Fence)) {
      *ppvObject = ref(this);
      return S_OK;
    }

    Logger::warn("D3D11Fence: Unknown interface query");
    Logger::warn(str::format(riid));
    return E_NOINTERFACE;
  }

  HRESULT STDMETHODCALLTYPE D3D11Fence::CreateSharedHandle(
    const SECURITY_ATTRIBUTES* pAttributes,
          DWORD               dwAccess,
          LPCWSTR             lpName,
          HANDLE*             pHandle) {
    if (!(m_flags & D3D11_FENCE_FLAG_SHARED))
      return E_INVALIDARG;

    if (pAttributes)
      Logger::warn(str::format("CreateSharedHandle: attributes ", pAttributes, " not handled"));
    if (dwAccess)
      Logger::warn(str::format("CreateSharedHandle: access ", dwAccess, " not handled"));
    if (lpName)
      Logger::warn(str::format("CreateSharedHandle: name ", dxvk::str::fromws(lpName), " not handled"));

    HANDLE sharedHandle = m_fence->sharedHandle();
    if (sharedHandle == INVALID_HANDLE_VALUE)
      return E_INVALIDARG;

    *pHandle = sharedHandle;
    return S_OK;
  }

  HRESULT STDMETHODCALLTYPE D3D11Fence::SetEventOnCompletion(
          UINT64              Value,
          HANDLE              hEvent) {
    // TODO in case of rewinds, the stored value may be higher.
    // For shared fences, calling vkWaitSemaphores here could alleviate the issue.

    m_fence->enqueueWait(Value, [hEvent] {
      SetEvent(hEvent);
    });

    return S_OK;
  }

  UINT64 STDMETHODCALLTYPE D3D11Fence::GetCompletedValue() {
    // TODO in the case of rewinds, the stored value may be higher.
    // For shared fences, calling vkGetSemaphoreCounterValue here could alleviate the issue.

    return m_fence->getValue();
  }

}


code:
#pragma once

#include "../dxvk/dxvk_fence.h"
#include "../dxvk/dxvk_gpu_query.h"

#include "d3d11_device_child.h"

namespace dxvk {

  class D3D11Fence : public D3D11DeviceChild<ID3D11Fence> {

  public:

    D3D11Fence(
            D3D11Device*        pDevice,
            UINT64              InitialValue,
            D3D11_FENCE_FLAG    Flags,
            HANDLE              hFence);

    ~D3D11Fence();

    HRESULT STDMETHODCALLTYPE QueryInterface(
            REFIID              riid,
            void**              ppvObject);

    HRESULT STDMETHODCALLTYPE CreateSharedHandle(
      const SECURITY_ATTRIBUTES* pAttributes,
            DWORD               dwAccess,
            LPCWSTR             lpName,
            HANDLE*             pHandle);

    HRESULT STDMETHODCALLTYPE SetEventOnCompletion(
            UINT64              Value,
            HANDLE              hEvent);

    UINT64 STDMETHODCALLTYPE GetCompletedValue();

    Rc<DxvkFence> GetFence() const {
      return m_fence;
    }

  private:

    Rc<DxvkFence> m_fence;
    D3D11_FENCE_FLAG m_flags;

  };

}


code:
#include "d3d11_context.h"
#include "d3d11_device.h"
#include "d3d11_gdi.h"

#include "../util/util_gdi.h"

namespace dxvk {

  D3D11GDISurface::D3D11GDISurface(
          ID3D11Resource*     pResource,
          UINT                Subresource)
  : m_resource    (pResource),
    m_subresource (Subresource),
    m_readback    (nullptr),
    m_hdc         (nullptr),
    m_hbitmap     (nullptr),
    m_acquired    (false) {
    // Allocate memory for the bitmap
    auto tex = GetCommonTexture(m_resource)->Desc();
    m_data.resize(tex->Width * tex->Height);

    // Create GDI DC
    D3DKMT_CREATEDCFROMMEMORY desc;
    desc.pMemory     = m_data.data();
    desc.Format      = D3DFMT_A8R8G8B8;
    desc.Width       = tex->Width;
    desc.Height      = tex->Height;
    desc.Pitch       = tex->Width * sizeof(uint32_t);
    desc.hDeviceDc   = CreateCompatibleDC(nullptr);
    desc.pColorTable = nullptr;
    desc.hDc         = nullptr;
    desc.hBitmap     = nullptr;

    if (D3DKMTCreateDCFromMemory(&desc))
      Logger::err(str::format("D3D11: Failed to create GDI DC"));

    m_hdc     = desc.hDc;
    m_hbitmap = desc.hBitmap;
  }

  D3D11GDISurface::~D3D11GDISurface() {
    if (m_readback)
      m_readback->Release();

    D3DKMT_DESTROYDCFROMMEMORY desc;
    desc.hDC     = m_hdc;
    desc.hBitmap = m_hbitmap;
    D3DKMTDestroyDCFromMemory(&desc);
  }

  HRESULT D3D11GDISurface::Acquire(BOOL Discard, HDC* phdc) {
    if (!phdc)
      return E_INVALIDARG;

    *phdc = nullptr;

    if (m_acquired)
      return DXGI_ERROR_INVALID_CALL;

    if (!Discard) {
      // Create a staging resource that we can map
      if (!m_readback && FAILED(CreateReadbackResource())) {
        Logger::err("D3D11: Failed to create GDI readback resource");
        return E_FAIL;
      }

      // Copy subresource to staging image
      Com<ID3D11Device>         device;
      Com<ID3D11DeviceContext>  context;

      m_resource->GetDevice(&device);
      device->GetImmediateContext(&context);

      context->CopySubresourceRegion(m_readback, 0,
        0, 0, 0, m_resource, m_subresource, nullptr);

      // Copy staging image to DC memory
      auto tex       = GetCommonTexture(m_resource)->Desc();
      auto rowData   = reinterpret_cast<char*>(m_data.data());
      auto rowLength = sizeof(uint32_t) * tex->Width;

      D3D11_MAPPED_SUBRESOURCE sr;
      context->Map(m_readback, 0, D3D11_MAP_READ, 0, &sr);

      for (uint32_t i = 0; i < tex->Height; i++) {
        std::memcpy(rowData + rowLength * i,
          reinterpret_cast<const char*>(sr.pData) + sr.RowPitch * i,
          rowLength);
      }

      context->Unmap(m_readback, 0);
    }

    m_acquired = true;
    *phdc      = m_hdc;
    return S_OK;
  }

  HRESULT D3D11GDISurface::Release(const RECT* pDirtyRect) {
    if (!m_acquired)
      return DXGI_ERROR_INVALID_CALL;

    Com<ID3D11Device>         device;
    Com<ID3D11DeviceContext>  context;

    m_resource->GetDevice(&device);
    device->GetImmediateContext(&context);

    // Commit changes made to the DC
    auto tex = GetCommonTexture(m_resource)->Desc();

    RECT rect;

    if (pDirtyRect) {
      rect.left   = std::max<LONG>(pDirtyRect->left,   0);
      rect.top    = std::max<LONG>(pDirtyRect->top,    0);
      rect.right  = std::min<LONG>(pDirtyRect->right,  tex->Width);
      rect.bottom = std::min<LONG>(pDirtyRect->bottom, tex->Height);
    } else {
      rect.left   = 0;
      rect.top    = 0;
      rect.right  = tex->Width;
      rect.bottom = tex->Height;
    }

    if (rect.left < rect.right && rect.top < rect.bottom) {
      D3D11_BOX box;
      box.left    = rect.left;
      box.top     = rect.top;
      box.front   = 0;
      box.right   = rect.right;
      box.bottom  = rect.bottom;
      box.back    = 1;

      context->UpdateSubresource(m_resource, m_subresource,
        &box, m_data.data() + rect.left,
        sizeof(uint32_t) * tex->Width,
        sizeof(uint32_t) * tex->Width * tex->Height);
    }

    m_acquired = false;
    return S_OK;
  }

  HRESULT D3D11GDISurface::CreateReadbackResource() {
    auto tex = GetCommonTexture(m_resource);

    Com<ID3D11Device>         device;
    Com<ID3D11DeviceContext>  context;

    m_resource->GetDevice(&device);
    device->GetImmediateContext(&context);

    D3D11_RESOURCE_DIMENSION dim = { };
    m_resource->GetType(&dim);

    VkImageSubresource sr = tex->GetSubresourceFromIndex(
      VK_IMAGE_ASPECT_COLOR_BIT, m_subresource);

    switch (dim) {
      case D3D11_RESOURCE_DIMENSION_TEXTURE1D: {
        D3D11_TEXTURE1D_DESC desc;
        desc.Width     = std::max<UINT>(tex->Desc()->Width >> sr.mipLevel, 1);
        desc.MipLevels = 1;
        desc.ArraySize = 1;
        desc.Format    = tex->Desc()->Format;
        desc.Usage     = D3D11_USAGE_STAGING;
        desc.BindFlags = 0;
        desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
        desc.MiscFlags = 0;

        ID3D11Texture1D* tex1D = nullptr;
        HRESULT hr = device->CreateTexture1D(&desc, nullptr, &tex1D);
        m_readback = tex1D;
        return hr;
      } break;

      case D3D11_RESOURCE_DIMENSION_TEXTURE2D: {
        D3D11_TEXTURE2D_DESC desc;
        desc.Width     = std::max<UINT>(tex->Desc()->Width  >> sr.mipLevel, 1);
        desc.Height    = std::max<UINT>(tex->Desc()->Height >> sr.mipLevel, 1);
        desc.MipLevels = 1;
        desc.ArraySize = 1;
        desc.Format    = tex->Desc()->Format;
        desc.SampleDesc= { 1, 0 };
        desc.Usage     = D3D11_USAGE_STAGING;
        desc.BindFlags = 0;
        desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
        desc.MiscFlags = 0;

        ID3D11Texture2D* tex2D = nullptr;
        HRESULT hr = device->CreateTexture2D(&desc, nullptr, &tex2D);
        m_readback = tex2D;
        return hr;
      } break;

      default:
        return E_INVALIDARG;
    }
  }

}


code:
#pragma once

#include <vector>

#include "d3d11_include.h"

namespace dxvk {

  class D3D11GDISurface {

  public:

    D3D11GDISurface(
            ID3D11Resource*     pResource,
            UINT                Subresource);

    ~D3D11GDISurface();

    HRESULT Acquire(
            BOOL                Discard,
            HDC*                phdc);

    HRESULT Release(
      const RECT*               pDirtyRect);

  private:

    ID3D11Resource* m_resource;
    uint32_t        m_subresource;
    ID3D11Resource* m_readback;
    HDC             m_hdc;
    HANDLE          m_hbitmap;
    bool            m_acquired;

    std::vector<uint32_t> m_data;

    HRESULT CreateReadbackResource();

  };

}


code:
#pragma once

#include "../dxgi/dxgi_include.h"

#include <d3d11_4.h>

// This is not defined in the mingw headers
#ifndef D3D11_1_UAV_SLOT_COUNT
#define D3D11_1_UAV_SLOT_COUNT 64
#endif

#ifndef D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL
#define D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL 0xFFFFFFFF
#endif

#ifndef D3D11_KEEP_UNORDERED_ACCESS_VIEWS
#define D3D11_KEEP_UNORDERED_ACCESS_VIEWS 0xFFFFFFFF
#endif

#define D3D11_DXVK_USE_REMAINING_LAYERS 0xFFFFFFFF
#define D3D11_DXVK_USE_REMAINING_LEVELS 0xFFFFFFFF

// Most of these were copied from d3d11.h
// For some strange reason, we cannot use the structures
// directly, although others from the same header work.
// Some structures are missing from the mingw headers.
#ifndef _MSC_VER
#if !defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 9
typedef enum D3D11_FORMAT_SUPPORT2 {
  D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_ADD                                = 0x1,
  D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_BITWISE_OPS                        = 0x2,
  D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_COMPARE_STORE_OR_COMPARE_EXCHANGE  = 0x4,
  D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_EXCHANGE                           = 0x8,
  D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_SIGNED_MIN_OR_MAX                  = 0x10,
  D3D11_FORMAT_SUPPORT2_UAV_ATOMIC_UNSIGNED_MIN_OR_MAX                = 0x20,
  D3D11_FORMAT_SUPPORT2_UAV_TYPED_LOAD                                = 0x40,
  D3D11_FORMAT_SUPPORT2_UAV_TYPED_STORE                               = 0x80,
  D3D11_FORMAT_SUPPORT2_OUTPUT_MERGER_LOGIC_OP                        = 0x100,
  D3D11_FORMAT_SUPPORT2_TILED                                         = 0x200,
  D3D11_FORMAT_SUPPORT2_SHAREABLE                                     = 0x400,
  D3D11_FORMAT_SUPPORT2_MULTIPLANE_OVERLAY                            = 0x4000
} D3D11_FORMAT_SUPPORT2;
#define D3D11_RESOURCE_MISC_TILE_POOL (0x20000)
#define D3D11_RESOURCE_MISC_TILED     (0x40000)
#endif // !defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 9
#endif // _MSC_VER


code:
#include <cstring>

#include "d3d11_device.h"
#include "d3d11_initializer.h"

namespace dxvk {

  D3D11Initializer::D3D11Initializer(
          D3D11Device*                pParent)
  : m_parent(pParent),
    m_device(pParent->GetDXVKDevice()),
    m_context(m_device->createContext()) {
    m_context->beginRecording(
      m_device->createCommandList());
  }

  D3D11Initializer::~D3D11Initializer() {

  }

  void D3D11Initializer::Flush() {
    std::lock_guard<dxvk::mutex> lock(m_mutex);

    if (m_transferCommands != 0)
      FlushInternal();
  }

  void D3D11Initializer::InitBuffer(
          D3D11Buffer*                pBuffer,
    const D3D11_SUBRESOURCE_DATA*     pInitialData) {
    VkMemoryPropertyFlags memFlags = pBuffer->GetBuffer()->memFlags();

    (memFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
      ? InitHostVisibleBuffer(pBuffer, pInitialData)
      : InitDeviceLocalBuffer(pBuffer, pInitialData);
  }

  void D3D11Initializer::InitTexture(
          D3D11CommonTexture*         pTexture,
    const D3D11_SUBRESOURCE_DATA*     pInitialData) {
    (pTexture->GetMapMode() == D3D11_COMMON_TEXTURE_MAP_MODE_DIRECT)
      ? InitHostVisibleTexture(pTexture, pInitialData)
      : InitDeviceLocalTexture(pTexture, pInitialData);
  }

  void D3D11Initializer::InitUavCounter(
          D3D11UnorderedAccessView*   pUav) {
    auto counterBuffer = pUav->GetCounterSlice();

    if (!counterBuffer.defined())
      return;

    std::lock_guard<dxvk::mutex> lock(m_mutex);
    m_transferCommands += 1;

    const uint32_t zero = 0;
    m_context->updateBuffer(
      counterBuffer.buffer(),
      0, sizeof(zero), &zero);

    FlushImplicit();
  }

  void D3D11Initializer::InitDeviceLocalBuffer(
          D3D11Buffer*                pBuffer,
    const D3D11_SUBRESOURCE_DATA*     pInitialData) {
    std::lock_guard<dxvk::mutex> lock(m_mutex);

    DxvkBufferSlice bufferSlice = pBuffer->GetBufferSlice();

    if (pInitialData != nullptr && pInitialData->pSysMem != nullptr) {
      m_transferMemory   += bufferSlice.length();
      m_transferCommands += 1;

      m_context->uploadBuffer(
        bufferSlice.buffer(),
        pInitialData->pSysMem);
    } else {
      m_transferCommands += 1;

      m_context->initBuffer(
        bufferSlice.buffer());
    }

    FlushImplicit();
  }

  void D3D11Initializer::InitHostVisibleBuffer(
          D3D11Buffer*                pBuffer,
    const D3D11_SUBRESOURCE_DATA*     pInitialData) {
    // If the buffer is mapped, we can write data directly
    // to the mapped memory region instead of doing it on
    // the GPU. Same goes for zero-initialization.
    DxvkBufferSlice bufferSlice = pBuffer->GetBufferSlice();

    if (pInitialData != nullptr && pInitialData->pSysMem != nullptr) {
      std::memcpy(
        bufferSlice.mapPtr(0),
        pInitialData->pSysMem,
        bufferSlice.length());
    } else {
      std::memset(
        bufferSlice.mapPtr(0), 0,
        bufferSlice.length());
    }
  }

  void D3D11Initializer::InitDeviceLocalTexture(
          D3D11CommonTexture*         pTexture,
    const D3D11_SUBRESOURCE_DATA*     pInitialData) {
    std::lock_guard<dxvk::mutex> lock(m_mutex);

    Rc<DxvkImage> image = pTexture->GetImage();

    auto mapMode = pTexture->GetMapMode();
    auto desc = pTexture->Desc();

    VkFormat packedFormat = m_parent->LookupPackedFormat(desc->Format, pTexture->GetFormatMode()).Format;
    auto formatInfo = imageFormatInfo(packedFormat);

    if (pInitialData != nullptr && pInitialData->pSysMem != nullptr) {
      // pInitialData is an array that stores an entry for
      // every single subresource. Since we will define all
      // subresources, this counts as initialization.
      for (uint32_t layer = 0; layer < desc->ArraySize; layer++) {
        for (uint32_t level = 0; level < desc->MipLevels; level++) {
          const uint32_t id = D3D11CalcSubresource(
            level, layer, desc->MipLevels);

          VkOffset3D mipLevelOffset = { 0, 0, 0 };
          VkExtent3D mipLevelExtent = pTexture->MipLevelExtent(level);

          if (mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_STAGING) {
            m_transferCommands += 1;
            m_transferMemory   += pTexture->GetSubresourceLayout(formatInfo->aspectMask, id).Size;

            VkImageSubresourceLayers subresourceLayers;
            subresourceLayers.aspectMask     = formatInfo->aspectMask;
            subresourceLayers.mipLevel       = level;
            subresourceLayers.baseArrayLayer = layer;
            subresourceLayers.layerCount     = 1;

            if (formatInfo->aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
              m_context->uploadImage(
                image, subresourceLayers,
                pInitialData[id].pSysMem,
                pInitialData[id].SysMemPitch,
                pInitialData[id].SysMemSlicePitch);
            } else {
              m_context->updateDepthStencilImage(
                image, subresourceLayers,
                VkOffset2D { mipLevelOffset.x,     mipLevelOffset.y      },
                VkExtent2D { mipLevelExtent.width, mipLevelExtent.height },
                pInitialData[id].pSysMem,
                pInitialData[id].SysMemPitch,
                pInitialData[id].SysMemSlicePitch,
                packedFormat);
            }
          }

          if (mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_NONE) {
            util::packImageData(pTexture->GetMappedBuffer(id)->mapPtr(0),
              pInitialData[id].pSysMem, pInitialData[id].SysMemPitch, pInitialData[id].SysMemSlicePitch,
              0, 0, pTexture->GetVkImageType(), mipLevelExtent, 1, formatInfo, formatInfo->aspectMask);
          }
        }
      }
    } else {
      if (mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_STAGING) {
        m_transferCommands += 1;

        // While the Microsoft docs state that resource contents are
        // undefined if no initial data is provided, some applications
        // expect a resource to be pre-cleared.
        VkImageSubresourceRange subresources;
        subresources.aspectMask     = formatInfo->aspectMask;
        subresources.baseMipLevel   = 0;
        subresources.levelCount     = desc->MipLevels;
        subresources.baseArrayLayer = 0;
        subresources.layerCount     = desc->ArraySize;

        m_context->initImage(image, subresources, VK_IMAGE_LAYOUT_UNDEFINED);
      }

      if (mapMode != D3D11_COMMON_TEXTURE_MAP_MODE_NONE) {
        for (uint32_t i = 0; i < pTexture->CountSubresources(); i++) {
          auto buffer = pTexture->GetMappedBuffer(i);
          std::memset(buffer->mapPtr(0), 0, buffer->info().size);
        }
      }
    }

    FlushImplicit();
  }

  void D3D11Initializer::InitHostVisibleTexture(
          D3D11CommonTexture*         pTexture,
    const D3D11_SUBRESOURCE_DATA*     pInitialData) {
    Rc<DxvkImage> image = pTexture->GetImage();

    for (uint32_t layer = 0; layer < image->info().numLayers; layer++) {
      for (uint32_t level = 0; level < image->info().mipLevels; level++) {
        VkImageSubresource subresource;
        subresource.aspectMask = image->formatInfo()->aspectMask;
        subresource.mipLevel   = level;
        subresource.arrayLayer = layer;

        VkExtent3D blockCount = util::computeBlockCount(
          image->mipLevelExtent(level),
          image->formatInfo()->blockSize);

        VkSubresourceLayout layout = image->querySubresourceLayout(subresource);

        auto initialData = pInitialData
          ? &pInitialData[D3D11CalcSubresource(level, layer, image->info().mipLevels)]
          : nullptr;

        for (uint32_t z = 0; z < blockCount.depth; z++) {
          for (uint32_t y = 0; y < blockCount.height; y++) {
            auto size = blockCount.width * image->formatInfo()->elementSize;
            auto dst = image->mapPtr(layout.offset + y * layout.rowPitch + z * layout.depthPitch);

            if (initialData) {
              auto src = reinterpret_cast<const char*>(initialData->pSysMem)
                       + y * initialData->SysMemPitch
                       + z * initialData->SysMemSlicePitch;
              std::memcpy(dst, src, size);
            } else {
              std::memset(dst, 0, size);
            }
          }
        }
      }
    }

    // Initialize the image on the GPU
    std::lock_guard<dxvk::mutex> lock(m_mutex);

    VkImageSubresourceRange subresources = image->getAvailableSubresources();

    m_context->initImage(image, subresources, VK_IMAGE_LAYOUT_PREINITIALIZED);

    m_transferCommands += 1;
    FlushImplicit();
  }

  void D3D11Initializer::FlushImplicit() {
    if (m_transferCommands > MaxTransferCommands
     || m_transferMemory   > MaxTransferMemory)
      FlushInternal();
  }

  void D3D11Initializer::FlushInternal() {
    m_context->flushCommandList();

    m_transferCommands = 0;
    m_transferMemory   = 0;
  }

}


code:
#pragma once

#include "d3d11_buffer.h"
#include "d3d11_texture.h"

namespace dxvk {

  class D3D11Device;

  /**
   * \brief Resource initialization context
   *
   * Manages a context which is used for resource
   * initialization. This includes initialization
   * with application-defined data, as well as
   * zero-initialization for buffers and images.
   */
  class D3D11Initializer {
    constexpr static size_t MaxTransferMemory    = 32 * 1024 * 1024;
    constexpr static size_t MaxTransferCommands  = 512;
  public:

    D3D11Initializer(
            D3D11Device*                pParent);

    ~D3D11Initializer();

    void Flush();

    void InitBuffer(
            D3D11Buffer*                pBuffer,
      const D3D11_SUBRESOURCE_DATA*     pInitialData);

    void InitTexture(
            D3D11CommonTexture*         pTexture,
      const D3D11_SUBRESOURCE_DATA*     pInitialData);

    void InitUavCounter(
            D3D11UnorderedAccessView*   pUav);

  private:

    dxvk::mutex       m_mutex;

    D3D11Device*      m_parent;
    Rc<DxvkDevice>    m_device;
    Rc<DxvkContext>   m_context;

    size_t            m_transferCommands  = 0;
    size_t            m_transferMemory    = 0;

    void InitDeviceLocalBuffer(
            D3D11Buffer*                pBuffer,
      const D3D11_SUBRESOURCE_DATA*     pInitialData);

    void InitHostVisibleBuffer(
            D3D11Buffer*                pBuffer,
      const D3D11_SUBRESOURCE_DATA*     pInitialData);

    void InitDeviceLocalTexture(
            D3D11CommonTexture*         pTexture,
      const D3D11_SUBRESOURCE_DATA*     pInitialData);

    void InitHostVisibleTexture(
            D3D11CommonTexture*         pTexture,
      const D3D11_SUBRESOURCE_DATA*     pInitialData);

    void FlushImplicit();
    void FlushInternal();

  };

}


code:
#include "d3d11_device.h"
#include "d3d11_input_layout.h"

namespace dxvk {

  D3D11InputLayout::D3D11InputLayout(
          D3D11Device*          pDevice,
          uint32_t              numAttributes,
    const DxvkVertexAttribute*  pAttributes,
          uint32_t              numBindings,
    const DxvkVertexBinding*    pBindings)
  : D3D11DeviceChild<ID3D11InputLayout>(pDevice),
    m_d3d10(this) {
    m_attributes.resize(numAttributes);
    m_bindings.resize(numBindings);

    for (uint32_t i = 0; i < numAttributes; i++)
      m_attributes.at(i) = pAttributes[i];

    for (uint32_t i = 0; i < numBindings; i++)
      m_bindings.at(i) = pBindings[i];
  }

  D3D11InputLayout::~D3D11InputLayout() {

  }

  HRESULT STDMETHODCALLTYPE D3D11InputLayout::QueryInterface(REFIID riid, void** ppvObject) {
    if (ppvObject == nullptr)
      return E_POINTER;

    *ppvObject = nullptr;

    if (riid == __uuidof(IUnknown)
     || riid == __uuidof(ID3D11DeviceChild)
     || riid == __uuidof(ID3D11InputLayout)) {
      *ppvObject = ref(this);
      return S_OK;
    }

    if (riid == __uuidof(ID3D10DeviceChild)
     || riid == __uuidof(ID3D10InputLayout)) {
      *ppvObject = ref(&m_d3d10);
      return S_OK;
    }

    Logger::warn("D3D11InputLayout::QueryInterface: Unknown interface query");
    Logger::warn(str::format(riid));
    return E_NOINTERFACE;
  }

  void D3D11InputLayout::BindToContext(const Rc<DxvkContext>& ctx) {
    ctx->setInputLayout(
      m_attributes.size(),
      m_attributes.data(),
      m_bindings.size(),
      m_bindings.data());
  }

  bool D3D11InputLayout::Compare(const D3D11InputLayout* pOther) const {
    bool eq = m_attributes.size() == pOther->m_attributes.size()
           && m_bindings.size()   == pOther->m_bindings.size();

    for (uint32_t i = 0; eq && i < m_attributes.size(); i++) {
      eq &= m_attributes[i].location == pOther->m_attributes[i].location
         && m_attributes[i].binding  == pOther->m_attributes[i].binding
         && m_attributes[i].format   == pOther->m_attributes[i].format
         && m_attributes[i].offset   == pOther->m_attributes[i].offset;
    }

    for (uint32_t i = 0; eq && i < m_bindings.size(); i++) {
      eq &= m_bindings[i].binding    == pOther->m_bindings[i].binding
         && m_bindings[i].fetchRate  == pOther->m_bindings[i].fetchRate
         && m_bindings[i].inputRate  == pOther->m_bindings[i].inputRate;
    }

    return eq;
  }

}


code:
#pragma once

#include "d3d11_device_child.h"

#include "../d3d10/d3d10_input_layout.h"

namespace dxvk {

  class D3D11Device;

  class D3D11InputLayout : public D3D11DeviceChild<ID3D11InputLayout> {

  public:

    D3D11InputLayout(
            D3D11Device*          pDevice,
            uint32_t              numAttributes,
      const DxvkVertexAttribute*  pAttributes,
            uint32_t              numBindings,
      const DxvkVertexBinding*    pBindings);

    ~D3D11InputLayout();

    HRESULT STDMETHODCALLTYPE QueryInterface(
            REFIID                riid,
            void**                ppvObject) final;

    void BindToContext(
      const Rc<DxvkContext>&      ctx);

    bool Compare(
      const D3D11InputLayout*     pOther) const;

    D3D10InputLayout* GetD3D10Iface() {
      return &m_d3d10;
    }

  private:

    std::vector<DxvkVertexAttribute> m_attributes;
    std::vector<DxvkVertexBinding>   m_bindings;

    D3D10InputLayout m_d3d10;

  };

}


code:
#pragma once

#include "../dxgi/dxgi_interfaces.h"

#include "d3d11_include.h"

/**
 * \brief D3D11 extension
 *
 * Lists D3D11 extensions supported by DXVK.
 */
enum D3D11_VK_EXTENSION : uint32_t {
  D3D11_VK_EXT_MULTI_DRAW_INDIRECT        = 0,
  D3D11_VK_EXT_MULTI_DRAW_INDIRECT_COUNT  = 1,
  D3D11_VK_EXT_DEPTH_BOUNDS               = 2,
  D3D11_VK_EXT_BARRIER_CONTROL            = 3,
  D3D11_VK_NVX_BINARY_IMPORT              = 4,
  D3D11_VK_NVX_IMAGE_VIEW_HANDLE          = 5,
};

/**
 * \brief Barrier control flags
 */
enum D3D11_VK_BARRIER_CONTROL : uint32_t {
  D3D11_VK_BARRIER_CONTROL_IGNORE_WRITE_AFTER_WRITE   = 1 << 0,
  D3D11_VK_BARRIER_CONTROL_IGNORE_GRAPHICS_UAV        = 1 << 1,
};

/**
 * \brief Extended D3D11 device
 *
 * Introduces a method to check for extension support.
 */
MIDL_INTERFACE("8a6e3c42-f74c-45b7-8265-a231b677ca17")
ID3D11VkExtDevice : public IUnknown {
  /**
   * \brief Checks whether an extension is supported
   *
   * \param [in] Extension The extension to check
   * \returns \c TRUE if the extension is supported
   */
  virtual BOOL STDMETHODCALLTYPE GetExtensionSupport(
          D3D11_VK_EXTENSION      Extension) = 0;

};

/**
 * \brief Extended extended D3D11 device
 *
 * Introduces methods to get virtual addresses and driver
 * handles for resources, and create and destroy objects
 * for D3D11-Cuda interop.
 */
MIDL_INTERFACE("cfcf64ef-9586-46d0-bca4-97cf2ca61b06")
ID3D11VkExtDevice1 : public ID3D11VkExtDevice {

  virtual bool STDMETHODCALLTYPE GetResourceHandleGPUVirtualAddressAndSizeNVX(
          void*                   hObject,
          uint64_t*               gpuVAStart,
          uint64_t*               gpuVASize) = 0;

  virtual bool STDMETHODCALLTYPE CreateUnorderedAccessViewAndGetDriverHandleNVX(
          ID3D11Resource*         pResource,
          const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc,
          ID3D11UnorderedAccessView** ppUAV,
          uint32_t*               pDriverHandle) = 0;

  virtual bool STDMETHODCALLTYPE CreateShaderResourceViewAndGetDriverHandleNVX(
          ID3D11Resource*         pResource,
          const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc,
          ID3D11ShaderResourceView** ppSRV,
          uint32_t*               pDriverHandle) = 0;

  virtual bool STDMETHODCALLTYPE CreateSamplerStateAndGetDriverHandleNVX(
          const D3D11_SAMPLER_DESC* pSamplerDesc,
          ID3D11SamplerState**    ppSamplerState,
          uint32_t*               pDriverHandle) = 0;

  virtual bool STDMETHODCALLTYPE CreateCubinComputeShaderWithNameNVX(
          const void*             pCubin,
          uint32_t                size,
          uint32_t                blockX,
          uint32_t                blockY,
          uint32_t                blockZ,
          const char*             pShaderName,
          IUnknown**              phShader) = 0;

  virtual bool STDMETHODCALLTYPE GetCudaTextureObjectNVX(
          uint32_t                srvDriverHandle,
          uint32_t                samplerDriverHandle,
          uint32_t*               pCudaTextureHandle) = 0;
};

/**
 * \brief Extended D3D11 context
 *
 * Provides functionality for various D3D11
 * extensions.
 */
MIDL_INTERFACE("fd0bca13-5cb6-4c3a-987e-4750de2ca791")
ID3D11VkExtContext : public IUnknown {
  virtual void STDMETHODCALLTYPE MultiDrawIndirect(
          UINT                    DrawCount,
          ID3D11Buffer*           pBufferForArgs,
          UINT                    ByteOffsetForArgs,
          UINT                    ByteStrideForArgs) = 0;

  virtual void STDMETHODCALLTYPE MultiDrawIndexedIndirect(
          UINT                    DrawCount,
          ID3D11Buffer*           pBufferForArgs,
          UINT                    ByteOffsetForArgs,
          UINT                    ByteStrideForArgs) = 0;

  virtual void STDMETHODCALLTYPE MultiDrawIndirectCount(
          UINT                    MaxDrawCount,
          ID3D11Buffer*           pBufferForCount,
          UINT                    ByteOffsetForCount,
          ID3D11Buffer*           pBufferForArgs,
          UINT                    ByteOffsetForArgs,
          UINT                    ByteStrideForArgs) = 0;

  virtual void STDMETHODCALLTYPE MultiDrawIndexedIndirectCount(
          UINT                    MaxDrawCount,
          ID3D11Buffer*           pBufferForCount,
          UINT                    ByteOffsetForCount,
          ID3D11Buffer*           pBufferForArgs,
          UINT                    ByteOffsetForArgs,
          UINT                    ByteStrideForArgs) = 0;

  virtual void STDMETHODCALLTYPE SetDepthBoundsTest(
          BOOL                    Enable,
          FLOAT                   MinDepthBounds,
          FLOAT                   MaxDepthBounds) = 0;

  virtual void STDMETHODCALLTYPE SetBarrierControl(
          UINT                    ControlFlags) = 0;
};

/**
 * \brief Extended extended D3D11 context
 *
 * Provides functionality to launch a Cuda kernel
 */
MIDL_INTERFACE("874b09b2-ae0b-41d8-8476-5f3b7a0e879d")
ID3D11VkExtContext1 : public ID3D11VkExtContext {

  virtual bool STDMETHODCALLTYPE LaunchCubinShaderNVX(
          IUnknown*               hShader,
          uint32_t                gridX,
          uint32_t                gridY,
          uint32_t                gridZ,
          const void*             pParams,
          uint32_t                paramSize,
          void* const*            pReadResources,
          uint32_t                numReadResources,
          void* const*            pWriteResources,
          uint32_t                numWriteResources) = 0;
};

#ifdef _MSC_VER
struct __declspec(uuid("8a6e3c42-f74c-45b7-8265-a231b677ca17")) ID3D11VkExtDevice;
struct __declspec(uuid("cfcf64ef-9586-46d0-bca4-97cf2ca61b06")) ID3D11VkExtDevice1;
struct __declspec(uuid("fd0bca13-5cb6-4c3a-987e-4750de2ca791")) ID3D11VkExtContext;
struct __declspec(uuid("874b09b2-ae0b-41d8-8476-5f3b7a0e879d")) ID3D11VkExtContext1;
#else
__CRT_UUID_DECL(ID3D11VkExtDevice,         0x8a6e3c42,0xf74c,0x45b7,0x82,0x65,0xa2,0x31,0xb6,0x77,0xca,0x17);
__CRT_UUID_DECL(ID3D11VkExtDevice1,        0xcfcf64ef,0x9586,0x46d0,0xbc,0xa4,0x97,0xcf,0x2c,0xa6,0x1b,0x06);
__CRT_UUID_DECL(ID3D11VkExtContext,        0xfd0bca13,0x5cb6,0x4c3a,0x98,0x7e,0x47,0x50,0xde,0x2c,0xa7,0x91);
__CRT_UUID_DECL(ID3D11VkExtContext1,       0x874b09b2,0xae0b,0x41d8,0x84,0x76,0x5f,0x3b,0x7a,0x0e,0x87,0x9d);
#endif


code:
#include "d3d11_context_imm.h"
#include "d3d11_interop.h"
#include "d3d11_device.h"

#include "../dxvk/dxvk_adapter.h"
#include "../dxvk/dxvk_device.h"
#include "../dxvk/dxvk_instance.h"

namespace dxvk {

  D3D11VkInterop::D3D11VkInterop(
          IDXGIObject*          pContainer,
          D3D11Device*          pDevice)
  : m_container (pContainer),
    m_device    (pDevice) { }

  D3D11VkInterop::~D3D11VkInterop() {

  }

  ULONG STDMETHODCALLTYPE D3D11VkInterop::AddRef() {
    return m_container->AddRef();
  }

  ULONG STDMETHODCALLTYPE D3D11VkInterop::Release() {
    return m_container->Release();
  }

  HRESULT STDMETHODCALLTYPE D3D11VkInterop::QueryInterface(
          REFIID                riid,
          void**                ppvObject) {
    return m_container->QueryInterface(riid, ppvObject);
  }

  void STDMETHODCALLTYPE D3D11VkInterop::GetVulkanHandles(
          VkInstance*           pInstance,
          VkPhysicalDevice*     pPhysDev,
          VkDevice*             pDevice) {
    auto device   = m_device->GetDXVKDevice();
    auto adapter  = device->adapter();
    auto instance = device->instance();

    if (pDevice != nullptr)
      *pDevice = device->handle();

    if (pPhysDev != nullptr)
      *pPhysDev = adapter->handle();

    if (pInstance != nullptr)
      *pInstance = instance->handle();
  }

  void STDMETHODCALLTYPE D3D11VkInterop::GetSubmissionQueue(
          VkQueue*              pQueue,
          uint32_t*             pQueueFamilyIndex) {
    auto device = static_cast<D3D11Device*>(m_device)->GetDXVKDevice();
    DxvkDeviceQueue queue = device->queues().graphics;

    if (pQueue != nullptr)
      *pQueue = queue.queueHandle;

    if (pQueueFamilyIndex != nullptr)
      *pQueueFamilyIndex = queue.queueFamily;
  }

  void STDMETHODCALLTYPE D3D11VkInterop::TransitionSurfaceLayout(
          IDXGIVkInteropSurface*    pSurface,
    const VkImageSubresourceRange*  pSubresources,
          VkImageLayout             OldLayout,
          VkImageLayout             NewLayout) {
    Com<ID3D11DeviceContext> deviceContext = nullptr;
    m_device->GetImmediateContext(&deviceContext);

    auto immediateContext = static_cast<D3D11ImmediateContext*>(deviceContext.ptr());

    immediateContext->TransitionSurfaceLayout(
      pSurface, pSubresources, OldLayout, NewLayout);
  }

  void STDMETHODCALLTYPE D3D11VkInterop::FlushRenderingCommands() {
    Com<ID3D11DeviceContext> deviceContext = nullptr;
    m_device->GetImmediateContext(&deviceContext);

    auto immediateContext = static_cast<D3D11ImmediateContext*>(deviceContext.ptr());
    immediateContext->Flush();
    immediateContext->SynchronizeCsThread(DxvkCsThread::SynchronizeAll);
  }

  void STDMETHODCALLTYPE D3D11VkInterop::LockSubmissionQueue() {
    m_device->GetDXVKDevice()->lockSubmission();
  }

  void STDMETHODCALLTYPE D3D11VkInterop::ReleaseSubmissionQueue() {
    m_device->GetDXVKDevice()->unlockSubmission();
  }

  void STDMETHODCALLTYPE D3D11VkInterop::GetSubmissionQueue1(
          VkQueue*              pQueue,
          uint32_t*             pQueueIndex,
          uint32_t*             pQueueFamilyIndex) {
    auto device = static_cast<D3D11Device*>(m_device)->GetDXVKDevice();
    DxvkDeviceQueue queue = device->queues().graphics;

    if (pQueue != nullptr)
      *pQueue = queue.queueHandle;

    if (pQueueIndex != nullptr)
      *pQueueIndex = queue.queueIndex;

    if (pQueueFamilyIndex != nullptr)
      *pQueueFamilyIndex = queue.queueFamily;
  }

  HRESULT STDMETHODCALLTYPE D3D11VkInterop::CreateTexture2DFromVkImage(
          const D3D11_TEXTURE2D_DESC1 *pDesc,
          VkImage vkImage,
          ID3D11Texture2D **ppTexture2D) {

    InitReturnPtr(ppTexture2D);

    if (!pDesc)
      return E_INVALIDARG;

    D3D11_COMMON_TEXTURE_DESC desc;
    desc.Width          = pDesc->Width;
    desc.Height         = pDesc->Height;
    desc.Depth          = 1;
    desc.MipLevels      = pDesc->MipLevels;
    desc.ArraySize      = pDesc->ArraySize;
    desc.Format         = pDesc->Format;
    desc.SampleDesc     = pDesc->SampleDesc;
    desc.Usage          = pDesc->Usage;
    desc.BindFlags      = pDesc->BindFlags;
    desc.CPUAccessFlags = pDesc->CPUAccessFlags;
    desc.MiscFlags      = pDesc->MiscFlags;
    desc.TextureLayout  = pDesc->TextureLayout;

    HRESULT hr = D3D11CommonTexture::NormalizeTextureProperties(&desc);

    if (FAILED(hr))
      return hr;

    if (!ppTexture2D)
      return S_FALSE;

    try {
      Com<D3D11Texture2D> texture = new D3D11Texture2D(m_device, &desc, 0, vkImage);
      *ppTexture2D = texture.ref();
      return S_OK;
    } catch (const DxvkError& e) {
      Logger::err(e.message());
      return E_INVALIDARG;
    }
  }
}


code:
#pragma once

#include "../dxgi/dxgi_interfaces.h"

#include "d3d11_include.h"

namespace dxvk {

  class D3D11Device;

  class D3D11VkInterop : public ComObject<IDXGIVkInteropDevice1> {

  public:

    D3D11VkInterop(
            IDXGIObject*          pContainer,
            D3D11Device*          pDevice);

    ~D3D11VkInterop();

    ULONG STDMETHODCALLTYPE AddRef();

    ULONG STDMETHODCALLTYPE Release();

    HRESULT STDMETHODCALLTYPE QueryInterface(
            REFIID                riid,
            void**                ppvObject);

    void STDMETHODCALLTYPE GetVulkanHandles(
            VkInstance*           pInstance,
            VkPhysicalDevice*     pPhysDev,
            VkDevice*             pDevice);

    void STDMETHODCALLTYPE GetSubmissionQueue(
            VkQueue*              pQueue,
            uint32_t*             pQueueFamilyIndex);

    void STDMETHODCALLTYPE TransitionSurfaceLayout(
            IDXGIVkInteropSurface*    pSurface,
      const VkImageSubresourceRange*  pSubresources,
            VkImageLayout             OldLayout,
            VkImageLayout             NewLayout);

    void STDMETHODCALLTYPE FlushRenderingCommands();

    void STDMETHODCALLTYPE LockSubmissionQueue();

    void STDMETHODCALLTYPE ReleaseSubmissionQueue();

    void STDMETHODCALLTYPE GetSubmissionQueue1(
            VkQueue*              pQueue,
            uint32_t*             pQueueIndex,
            uint32_t*             pQueueFamilyIndex);

    HRESULT STDMETHODCALLTYPE CreateTexture2DFromVkImage(
            const D3D11_TEXTURE2D_DESC1* pDesc,
            VkImage                      vkImage,
            ID3D11Texture2D**            ppTexture2D);

  private:

    IDXGIObject* m_container;
    D3D11Device* m_device;

  };

}


code:
#include <array>

#include "../dxgi/dxgi_adapter.h"

#include "../dxvk/dxvk_instance.h"

#include "d3d11_device.h"
#include "d3d11_enums.h"
#include "d3d11_interop.h"

namespace dxvk {
  Logger Logger::s_instance("d3d11.log");
}

extern "C" {
  using namespace dxvk;

  DLLEXPORT HRESULT __stdcall D3D11CoreCreateDevice(
          IDXGIFactory*       pFactory,
          IDXGIAdapter*       pAdapter,
          UINT                Flags,
    const D3D_FEATURE_LEVEL*  pFeatureLevels,
          UINT                FeatureLevels,
          ID3D11Device**      ppDevice) {
    InitReturnPtr(ppDevice);

    Rc<DxvkAdapter>  dxvkAdapter;
    Rc<DxvkInstance> dxvkInstance;

    Com<IDXGIDXVKAdapter> dxgiVkAdapter;

    // Try to find the corresponding Vulkan device for the DXGI adapter
    if (SUCCEEDED(pAdapter->QueryInterface(__uuidof(IDXGIDXVKAdapter), reinterpret_cast<void**>(&dxgiVkAdapter)))) {
      dxvkAdapter  = dxgiVkAdapter->GetDXVKAdapter();
      dxvkInstance = dxgiVkAdapter->GetDXVKInstance();
    } else {
      Logger::warn("D3D11CoreCreateDevice: Adapter is not a DXVK adapter");
      DXGI_ADAPTER_DESC desc;
      pAdapter->GetDesc(&desc);

      dxvkInstance = new DxvkInstance();
      dxvkAdapter  = dxvkInstance->findAdapterByLuid(&desc.AdapterLuid);

      if (dxvkAdapter == nullptr)
        dxvkAdapter = dxvkInstance->findAdapterByDeviceId(desc.VendorId, desc.DeviceId);

      if (dxvkAdapter == nullptr)
        dxvkAdapter = dxvkInstance->enumAdapters(0);

      if (dxvkAdapter == nullptr)
        return E_FAIL;
    }

    // Feature levels to probe if the
    // application does not specify any.
    std::array<D3D_FEATURE_LEVEL, 6> defaultFeatureLevels = {
      D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1,
      D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3,
      D3D_FEATURE_LEVEL_9_2,  D3D_FEATURE_LEVEL_9_1,
    };

    if (pFeatureLevels == nullptr || FeatureLevels == 0) {
      pFeatureLevels = defaultFeatureLevels.data();
      FeatureLevels  = defaultFeatureLevels.size();
    }

    // Find the highest feature level supported by the device.
    // This works because the feature level array is ordered.
    UINT flId;

    for (flId = 0 ; flId < FeatureLevels; flId++) {
      Logger::info(str::format("D3D11CoreCreateDevice: Probing ", pFeatureLevels[flId]));

      if (D3D11Device::CheckFeatureLevelSupport(dxvkInstance, dxvkAdapter, pFeatureLevels[flId]))
        break;
    }

    if (flId == FeatureLevels) {
      Logger::err("D3D11CoreCreateDevice: Requested feature level not supported");
      return E_INVALIDARG;
    }

    // Try to create the device with the given parameters.
    const D3D_FEATURE_LEVEL fl = pFeatureLevels[flId];

    try {
      Logger::info(str::format("D3D11CoreCreateDevice: Using feature level ", fl));
      Com<D3D11DXGIDevice> device = new D3D11DXGIDevice(
        pAdapter, dxvkInstance, dxvkAdapter, fl, Flags);

      return device->QueryInterface(
        __uuidof(ID3D11Device),
        reinterpret_cast<void**>(ppDevice));
    } catch (const DxvkError& e) {
      Logger::err("D3D11CoreCreateDevice: Failed to create D3D11 device");
      return E_FAIL;
    }
  }

  static HRESULT D3D11InternalCreateDeviceAndSwapChain(
          IDXGIAdapter*         pAdapter,
          D3D_DRIVER_TYPE       DriverType,
          HMODULE               Software,
          UINT                  Flags,
    const D3D_FEATURE_LEVEL*    pFeatureLevels,
          UINT                  FeatureLevels,
          UINT                  SDKVersion,
    const DXGI_SWAP_CHAIN_DESC* pSwapChainDesc,
          IDXGISwapChain**      ppSwapChain,
          ID3D11Device**        ppDevice,
          D3D_FEATURE_LEVEL*    pFeatureLevel,
          ID3D11DeviceContext** ppImmediateContext) {
    InitReturnPtr(ppDevice);
    InitReturnPtr(ppSwapChain);
    InitReturnPtr(ppImmediateContext);

    if (pFeatureLevel)
      *pFeatureLevel = D3D_FEATURE_LEVEL(0);

    HRESULT hr;

    Com<IDXGIFactory> dxgiFactory = nullptr;
    Com<IDXGIAdapter> dxgiAdapter = pAdapter;
    Com<ID3D11Device> device      = nullptr;

    if (ppSwapChain && !pSwapChainDesc)
      return E_INVALIDARG;

    if (!pAdapter) {
      // We'll treat everything as hardware, even if the
      // Vulkan device is actually a software device.
      if (DriverType != D3D_DRIVER_TYPE_HARDWARE)
        Logger::warn("D3D11CreateDevice: Unsupported driver type");

      // We'll use the first adapter returned by a DXGI factory
      hr = CreateDXGIFactory1(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&dxgiFactory));

      if (FAILED(hr)) {
        Logger::err("D3D11CreateDevice: Failed to create a DXGI factory");
        return hr;
      }

      hr = dxgiFactory->EnumAdapters(0, &dxgiAdapter);

      if (FAILED(hr)) {
        Logger::err("D3D11CreateDevice: No default adapter available");
        return hr;
      }
    } else {
      // We should be able to query the DXGI factory from the adapter
      if (FAILED(dxgiAdapter->GetParent(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&dxgiFactory)))) {
        Logger::err("D3D11CreateDevice: Failed to query DXGI factory from DXGI adapter");
        return E_INVALIDARG;
      }

      // In theory we could ignore these, but the Microsoft docs explicitly
      // state that we need to return E_INVALIDARG in case the arguments are
      // invalid. Both the driver type and software parameter can only be
      // set if the adapter itself is unspecified.
      // See: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476082(v=vs.85).aspx
      if (DriverType != D3D_DRIVER_TYPE_UNKNOWN || Software)
        return E_INVALIDARG;
    }

    // Create the actual device
    hr = D3D11CoreCreateDevice(
      dxgiFactory.ptr(), dxgiAdapter.ptr(),
      Flags, pFeatureLevels, FeatureLevels,
      &device);

    if (FAILED(hr))
      return hr;

    // Create the swap chain, if requested
    if (ppSwapChain) {
      DXGI_SWAP_CHAIN_DESC desc = *pSwapChainDesc;
      hr = dxgiFactory->CreateSwapChain(device.ptr(), &desc, ppSwapChain);

      if (FAILED(hr)) {
        Logger::err("D3D11CreateDevice: Failed to create swap chain");
        return hr;
      }
    }

    // Write back whatever info the application requested
    if (pFeatureLevel)
      *pFeatureLevel = device->GetFeatureLevel();

    if (ppDevice)
      *ppDevice = device.ref();

    if (ppImmediateContext)
      device->GetImmediateContext(ppImmediateContext);

    // If we were unable to write back the device and the
    // swap chain, the application has no way of working
    // with the device so we should report S_FALSE here.
    if (!ppDevice && !ppImmediateContext && !ppSwapChain)
      return S_FALSE;

    return S_OK;
  }

  DLLEXPORT HRESULT __stdcall D3D11CreateDevice(
          IDXGIAdapter*         pAdapter,
          D3D_DRIVER_TYPE       DriverType,
          HMODULE               Software,
          UINT                  Flags,
    const D3D_FEATURE_LEVEL*    pFeatureLevels,
          UINT                  FeatureLevels,
          UINT                  SDKVersion,
          ID3D11Device**        ppDevice,
          D3D_FEATURE_LEVEL*    pFeatureLevel,
          ID3D11DeviceContext** ppImmediateContext) {
    return D3D11InternalCreateDeviceAndSwapChain(
      pAdapter, DriverType, Software, Flags,
      pFeatureLevels, FeatureLevels, SDKVersion,
      nullptr, nullptr,
      ppDevice, pFeatureLevel, ppImmediateContext);
  }

  DLLEXPORT HRESULT __stdcall D3D11CreateDeviceAndSwapChain(
          IDXGIAdapter*         pAdapter,
          D3D_DRIVER_TYPE       DriverType,
          HMODULE               Software,
          UINT                  Flags,
    const D3D_FEATURE_LEVEL*    pFeatureLevels,
          UINT                  FeatureLevels,
          UINT                  SDKVersion,
    const DXGI_SWAP_CHAIN_DESC* pSwapChainDesc,
          IDXGISwapChain**      ppSwapChain,
          ID3D11Device**        ppDevice,
          D3D_FEATURE_LEVEL*    pFeatureLevel,
          ID3D11DeviceContext** ppImmediateContext) {
    return D3D11InternalCreateDeviceAndSwapChain(
      pAdapter, DriverType, Software, Flags,
      pFeatureLevels, FeatureLevels, SDKVersion,
      pSwapChainDesc, ppSwapChain,
      ppDevice, pFeatureLevel, ppImmediateContext);
  }

  DLLEXPORT HRESULT __stdcall D3D11On12CreateDevice(
          IUnknown*             pDevice,
          UINT                  Flags,
    const D3D_FEATURE_LEVEL*    pFeatureLevels,
          UINT                  FeatureLevels,
          IUnknown* const*      ppCommandQueues,
          UINT                  NumQueues,
          UINT                  NodeMask,
          ID3D11Device**        ppDevice,
          ID3D11DeviceContext** ppImmediateContext,
          D3D_FEATURE_LEVEL*    pChosenFeatureLevel) {
    static bool s_errorShown = false;

    if (!std::exchange(s_errorShown, true))
      Logger::err("D3D11On12CreateDevice: Not implemented");

    return E_NOTIMPL;
  }

}


code:
#include <unordered_map>

#include "d3d11_options.h"

namespace dxvk {

  D3D11Options::D3D11Options(const Config& config, const Rc<DxvkDevice>& device) {
    const DxvkDeviceInfo& devInfo = device->properties();

    this->dcSingleUseMode       = config.getOption<bool>("d3d11.dcSingleUseMode", true);
    this->enableRtOutputNanFixup   = config.getOption<bool>("d3d11.enableRtOutputNanFixup", false);
    this->zeroInitWorkgroupMemory  = config.getOption<bool>("d3d11.zeroInitWorkgroupMemory", false);
    this->forceTgsmBarriers     = config.getOption<bool>("d3d11.forceTgsmBarriers", false);
    this->relaxedBarriers       = config.getOption<bool>("d3d11.relaxedBarriers", false);
    this->ignoreGraphicsBarriers = config.getOption<bool>("d3d11.ignoreGraphicsBarriers", false);
    this->maxTessFactor         = config.getOption<int32_t>("d3d11.maxTessFactor", 0);
    this->samplerAnisotropy     = config.getOption<int32_t>("d3d11.samplerAnisotropy", -1);
    this->invariantPosition     = config.getOption<bool>("d3d11.invariantPosition", true);
    this->floatControls         = config.getOption<bool>("d3d11.floatControls", true);
    this->disableMsaa           = config.getOption<bool>("d3d11.disableMsaa", false);
    this->deferSurfaceCreation  = config.getOption<bool>("dxgi.deferSurfaceCreation", false);
    this->numBackBuffers        = config.getOption<int32_t>("dxgi.numBackBuffers", 0);
    this->maxFrameLatency       = config.getOption<int32_t>("dxgi.maxFrameLatency", 0);
    this->maxFrameRate          = config.getOption<int32_t>("dxgi.maxFrameRate", 0);
    this->syncInterval          = config.getOption<int32_t>("dxgi.syncInterval", -1);
    this->tearFree              = config.getOption<Tristate>("dxgi.tearFree", Tristate::Auto);

    int32_t maxImplicitDiscardSize = config.getOption<int32_t>("d3d11.maxImplicitDiscardSize", 256);
    this->maxImplicitDiscardSize = maxImplicitDiscardSize >= 0
      ? VkDeviceSize(maxImplicitDiscardSize) << 10
      : VkDeviceSize(~0ull);

    int32_t maxDynamicImageBufferSize = config.getOption<int32_t>("d3d11.maxDynamicImageBufferSize", -1);
    this->maxDynamicImageBufferSize = maxDynamicImageBufferSize >= 0
      ? VkDeviceSize(maxDynamicImageBufferSize) << 10
      : VkDeviceSize(~0ull);

    this->constantBufferRangeCheck = config.getOption<bool>("d3d11.constantBufferRangeCheck", false)
      && DxvkGpuVendor(devInfo.core.properties.vendorID) != DxvkGpuVendor::Amd;

    auto cachedDynamicResources = config.getOption<std::string>("d3d11.cachedDynamicResources", std::string());

    if (::GetModuleHandle("dxgitrace.dll")) {
      // apitrace reads back all mapped resources on the CPU, so
      // allocating everything in cached memory is necessary to
      // achieve acceptable performance
      this->cachedDynamicResources = ~0u;
    } else {
      this->cachedDynamicResources = 0u;

      for (char c : cachedDynamicResources) {
        switch (c) {
          case 'c': this->cachedDynamicResources |= D3D11_BIND_CONSTANT_BUFFER;   break;
          case 'v': this->cachedDynamicResources |= D3D11_BIND_VERTEX_BUFFER;     break;
          case 'i': this->cachedDynamicResources |= D3D11_BIND_INDEX_BUFFER;      break;
          case 'r': this->cachedDynamicResources |= D3D11_BIND_SHADER_RESOURCE;   break;
          case 'a': this->cachedDynamicResources  = ~0u;                          break;
          default:  Logger::warn(str::format("Unknown flag for d3d11.cachedDynamicResources option: ", c));
        }
      }
    }
  }

}


code:
#pragma once

#include "../util/config/config.h"

#include "../dxgi/dxgi_options.h"

#include "../dxvk/dxvk_device.h"

#include "d3d11_include.h"

namespace dxvk {

  struct D3D11Options {
    D3D11Options(const Config& config, const Rc<DxvkDevice>& device);

    /// Enables speed hack for mapping on deferred contexts
    ///
    /// This can substantially speed up some games, but may
    /// cause issues if the game submits command lists more
    /// than once.
    bool dcSingleUseMode;

    /// Enables workaround to replace NaN render target
    /// outputs with zero
    bool enableRtOutputNanFixup;

    /// Enables out-of-bounds access check for constant
    /// buffers. Workaround for a few broken games that
    /// access random data inside their shaders.
    bool constantBufferRangeCheck;

    /// Zero-initialize workgroup memory
    ///
    /// Workargound for games that don't initialize
    /// TGSM in compute shaders before reading it.
    bool zeroInitWorkgroupMemory;

    /// Force thread-group shared memory barriers
    ///
    /// Workaround for compute shaders that read and
    /// write from the same shared memory location
    /// without explicit synchronization.
    bool forceTgsmBarriers;

    /// Use relaxed memory barriers
    ///
    /// May improve performance in some games,
    /// but might also cause rendering issues.
    bool relaxedBarriers;

    /// Ignore graphics barriers
    ///
    /// May improve performance in some games,
    /// but might also cause rendering issues.
    bool ignoreGraphicsBarriers;

    /// Maximum tessellation factor.
    ///
    /// Limits tessellation factors in tessellation
    /// control shaders. Values from 8 to 64 are
    /// supported, other values will be ignored.
    int32_t maxTessFactor;

    /// Anisotropic filter override
    ///
    /// Enforces anisotropic filtering with the
    /// given anisotropy value for all samplers.
    int32_t samplerAnisotropy;

    /// Declare vertex positions in shaders as invariant
    bool invariantPosition;

    /// Enable float control bits
    bool floatControls;

    /// Back buffer count for the Vulkan swap chain.
    /// Overrides DXGI_SWAP_CHAIN_DESC::BufferCount.
    int32_t numBackBuffers;

    /// Sync interval. Overrides the value
    /// passed to IDXGISwapChain::Present.
    int32_t syncInterval;

    /// Tear-free mode if vsync is disabled
    /// Tearing mode if vsync is enabled
    Tristate tearFree;

    /// Override maximum frame latency if the app specifies
    /// a higher value. May help with frame timing issues.
    int32_t maxFrameLatency;

    /// Limit frame rate
    int32_t maxFrameRate;

    /// Limit discardable resource size
    VkDeviceSize maxImplicitDiscardSize;

    /// Limit size of buffer-mapped images
    VkDeviceSize maxDynamicImageBufferSize;

    /// Defer surface creation until first present call. This
    /// fixes issues with games that create multiple swap chains
    /// for a single window that may interfere with each other.
    bool deferSurfaceCreation;

    /// Forces the sample count of all textures to be 1, and
    /// performs the required shader and resolve fixups.
    bool disableMsaa;

    /// Dynamic resources with the given bind flags will be allocated
    /// in cached system memory. Enabled automatically when recording
    /// an api trace.
    uint32_t cachedDynamicResources;
  };

}