code:
#include "../d3d11/d3d11_options.h"

#include "dxbc_options.h"

namespace dxvk {

  DxbcOptions::DxbcOptions() {

  }

  DxbcOptions::DxbcOptions(const Rc<DxvkDevice>& device, const D3D11Options& options) {
    const Rc<DxvkAdapter> adapter = device->adapter();

    const DxvkDeviceFeatures& devFeatures = device->features();
    const DxvkDeviceInfo& devInfo = adapter->devicePropertiesExt();

    useDepthClipWorkaround
      = !devFeatures.extDepthClipEnable.depthClipEnable;
    useStorageImageReadWithoutFormat
      = devFeatures.core.features.shaderStorageImageReadWithoutFormat;
    useSubgroupOpsForAtomicCounters
      = (devInfo.coreSubgroup.supportedStages     & VK_SHADER_STAGE_COMPUTE_BIT)
     && (devInfo.coreSubgroup.supportedOperations & VK_SUBGROUP_FEATURE_BALLOT_BIT);
    useDemoteToHelperInvocation
      = (devFeatures.extShaderDemoteToHelperInvocation.shaderDemoteToHelperInvocation);
    useSubgroupOpsForEarlyDiscard
      = (devInfo.coreSubgroup.subgroupSize >= 4)
     && (devInfo.coreSubgroup.supportedStages     & VK_SHADER_STAGE_FRAGMENT_BIT)
     && (devInfo.coreSubgroup.supportedOperations & VK_SUBGROUP_FEATURE_BALLOT_BIT);
    useSdivForBufferIndex
      = adapter->matchesDriver(DxvkGpuVendor::Nvidia, VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR, 0, 0);

    switch (device->config().useRawSsbo) {
      case Tristate::Auto:  minSsboAlignment = devInfo.core.properties.limits.minStorageBufferOffsetAlignment; break;
      case Tristate::True:  minSsboAlignment =  4u; break;
      case Tristate::False: minSsboAlignment = ~0u; break;
    }

    invariantPosition        = options.invariantPosition;
    enableRtOutputNanFixup   = options.enableRtOutputNanFixup;
    zeroInitWorkgroupMemory  = options.zeroInitWorkgroupMemory;
    forceTgsmBarriers        = options.forceTgsmBarriers;
    disableMsaa              = options.disableMsaa;
    dynamicIndexedConstantBufferAsSsbo = options.constantBufferRangeCheck;

    // Disable subgroup early discard on Nvidia because it may hurt performance
    if (adapter->matchesDriver(DxvkGpuVendor::Nvidia, VK_DRIVER_ID_NVIDIA_PROPRIETARY_KHR, 0, 0))
      useSubgroupOpsForEarlyDiscard = false;

    // Figure out float control flags to match D3D11 rules
    if (options.floatControls) {
      if (devInfo.khrShaderFloatControls.shaderSignedZeroInfNanPreserveFloat32)
        floatControl.set(DxbcFloatControlFlag::PreserveNan32);
      if (devInfo.khrShaderFloatControls.shaderSignedZeroInfNanPreserveFloat64)
        floatControl.set(DxbcFloatControlFlag::PreserveNan64);

      if (devInfo.khrShaderFloatControls.denormBehaviorIndependence != VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_NONE) {
        if (devInfo.khrShaderFloatControls.shaderDenormFlushToZeroFloat32)
          floatControl.set(DxbcFloatControlFlag::DenormFlushToZero32);
        if (devInfo.khrShaderFloatControls.shaderDenormPreserveFloat64)
          floatControl.set(DxbcFloatControlFlag::DenormPreserve64);
      }
    }

    if (!devInfo.khrShaderFloatControls.shaderSignedZeroInfNanPreserveFloat32
     || adapter->matchesDriver(DxvkGpuVendor::Amd, VK_DRIVER_ID_MESA_RADV_KHR, 0, VK_MAKE_VERSION(20, 3, 0)))
      enableRtOutputNanFixup = true;
  }

}


code:
#pragma once

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

namespace dxvk {

  struct D3D11Options;

  enum class DxbcFloatControlFlag : uint32_t {
    DenormFlushToZero32,
    DenormPreserve64,
    PreserveNan32,
    PreserveNan64,
  };

  using DxbcFloatControlFlags = Flags<DxbcFloatControlFlag>;

  struct DxbcOptions {
    DxbcOptions();
    DxbcOptions(const Rc<DxvkDevice>& device, const D3D11Options& options);

    // Clamp oDepth in fragment shaders if the depth
    // clip device feature is not supported
    bool useDepthClipWorkaround = false;

    /// Use the ShaderImageReadWithoutFormat capability.
    bool useStorageImageReadWithoutFormat = false;

    /// Use subgroup operations to reduce the number of
    /// atomic operations for append/consume buffers.
    bool useSubgroupOpsForAtomicCounters = false;

    /// Use a SPIR-V extension to implement D3D-style discards
    bool useDemoteToHelperInvocation = false;

    /// Use subgroup operations to discard fragment
    /// shader invocations if derivatives remain valid.
    bool useSubgroupOpsForEarlyDiscard = false;

    /// Use SDiv instead of SHR to converte byte offsets to
    /// dword offsets. Fixes RE2 and DMC5 on Nvidia drivers.
    bool useSdivForBufferIndex = false;

    /// Enables NaN fixup for render target outputs
    bool enableRtOutputNanFixup = false;

    /// Implement dynamically indexed uniform buffers
    /// with storage buffers for tight bounds checking
    bool dynamicIndexedConstantBufferAsSsbo = false;

    /// Clear thread-group shared memory to zero
    bool zeroInitWorkgroupMemory = false;

    /// Declare vertex positions as invariant
    bool invariantPosition = false;

    /// Insert memory barriers after TGSM stoes
    bool forceTgsmBarriers = false;

    /// Replace ld_ms with ld
    bool disableMsaa = false;

    /// Float control flags
    DxbcFloatControlFlags floatControl;

    /// Minimum storage buffer alignment
    VkDeviceSize minSsboAlignment = 0;
  };

}

repo_name: orochi/dxvk


code:
#include <cstring>

#include "dxbc_reader.h"

namespace dxvk {

  DxbcTag DxbcReader::readTag() {
    DxbcTag tag;
    this->read(&tag, 4);
    return tag;
  }

  std::string DxbcReader::readString() {
    std::string result;

    while (m_data[m_pos] != '\0')
      result.push_back(m_data[m_pos++]);

    m_pos++;
    return result;
  }

  void DxbcReader::read(void* dst, size_t n) {
    if (m_pos + n > m_size)
      throw DxvkError("DxbcReader::read: Unexpected end of file");
    std::memcpy(dst, m_data + m_pos, n);
    m_pos += n;
  }

  void DxbcReader::skip(size_t n) {
    if (m_pos + n > m_size)
      throw DxvkError("DxbcReader::skip: Unexpected end of file");
    m_pos += n;
  }

  DxbcReader DxbcReader::clone(size_t pos) const {
    if (pos > m_size)
      throw DxvkError("DxbcReader::clone: Invalid offset");
    return DxbcReader(m_data + pos, m_size - pos);
  }

  DxbcReader DxbcReader::resize(size_t size) const {
    if (size > m_size)
      throw DxvkError("DxbcReader::resize: Invalid size");
    return DxbcReader(m_data, size, m_pos);
  }

  void DxbcReader::store(std::ostream&& stream) const {
    stream.write(m_data, m_size);
  }

}


code:
#pragma once

#include <cstddef>
#include <string>

#include "dxbc_tag.h"

namespace dxvk {

  /**
   * \brief DXBC bytecode reader
   *
   * Holds references to the shader byte code and
   * provides methods to read
   */
  class DxbcReader {

  public:

    DxbcReader(const char* data, size_t size)
    : DxbcReader(data, size, 0) { }

    auto readu8 () { return this->readNum<uint8_t> (); }
    auto readu16() { return this->readNum<uint16_t>(); }
    auto readu32() { return this->readNum<uint32_t>(); }
    auto readu64() { return this->readNum<uint64_t>(); }

    auto readi8 () { return this->readNum<int8_t>  (); }
    auto readi16() { return this->readNum<int16_t> (); }
    auto readi32() { return this->readNum<int32_t> (); }
    auto readi64() { return this->readNum<int64_t> (); }

    auto readf32() { return this->readNum<float>   (); }
    auto readf64() { return this->readNum<double>  (); }

    template<typename T>
    auto readEnum() {
      using Tx = std::underlying_type_t<T>;
      return static_cast<T>(this->readNum<Tx>());
    }

    DxbcTag readTag();

    std::string readString();

    void read(void* dst, size_t n);

    void skip(size_t n);

    DxbcReader clone(size_t pos) const;

    DxbcReader resize(size_t size) const;

    bool eof() const {
      return m_pos >= m_size;
    }

    void store(std::ostream&& stream) const;

  private:

    DxbcReader(const char* data, size_t size, size_t pos)
    : m_data(data), m_size(size), m_pos(pos) { }

    const char* m_data = nullptr;
    size_t      m_size = 0;
    size_t      m_pos  = 0;

    template<typename T>
    T readNum() {
      T result;
      this->read(&result, sizeof(result));
      return result;
    }

  };

}


code:
#pragma once

#include "dxbc_include.h"

namespace dxvk {

  /**
   * \brief Four-character tag
   *
   * Used to identify chunks in the
   * compiled DXBC file by name.
   */
  class DxbcTag {

  public:

    DxbcTag() {
      for (size_t i = 0; i < 4; i++)
        m_chars[i] = '\0';
    }

    DxbcTag(const char* tag) {
      for (size_t i = 0; i < 4; i++)
        m_chars[i] = tag[i];
    }

    bool operator == (const DxbcTag& other) const {
      bool result = true;
      for (size_t i = 0; i < 4; i++)
        result &= m_chars[i] == other.m_chars[i];
      return result;
    }

    bool operator != (const DxbcTag& other) const {
      return !this->operator == (other);
    }

    const char* operator & () const { return m_chars; }
          char* operator & ()       { return m_chars; }

  private:

    char m_chars[4];

  };

}


code:
#include "dxbc_util.h"

namespace dxvk {

  uint32_t primitiveVertexCount(DxbcPrimitive primitive) {
    static const std::array<uint32_t, 8> s_vertexCounts = {
       0, // Undefined
       1, // Point
       2, // Line
       3, // Triangle
       0, // Undefined
       0, // Undefined
       4, // Line with adjacency
       6, // Triangle with adjacency
    };

    if (primitive >= DxbcPrimitive::Patch1) {
      return static_cast<uint32_t>(primitive)
           - static_cast<uint32_t>(DxbcPrimitive::Patch1);
    } else {
      return s_vertexCounts.at(
        static_cast<uint32_t>(primitive));
    }
  }

}


code:
#pragma once

#include "dxbc_common.h"
#include "dxbc_enums.h"

namespace dxvk {

  /**
   * \brief Binding numbers and properties
   */
  enum DxbcBindingProperties : uint32_t {
    DxbcConstBufBindingIndex  = 0,
    DxbcConstBufBindingCount  = 16,
    DxbcSamplerBindingIndex   = DxbcConstBufBindingIndex
                              + DxbcConstBufBindingCount,
    DxbcSamplerBindingCount   = 16,
    DxbcResourceBindingIndex  = DxbcSamplerBindingIndex
                              + DxbcSamplerBindingCount,
    DxbcResourceBindingCount  = 128,
    DxbcStageBindingCount     = DxbcConstBufBindingCount
                              + DxbcSamplerBindingCount
                              + DxbcResourceBindingCount,
    DxbcUavBindingIndex       = DxbcStageBindingCount * 6,
    DxbcUavBindingCount       = 64,
  };

  /**
   * \brief Computes first binding index for a given stage
   *
   * \param [in] stage The shader stage
   * \returns Index of first binding
   */
  inline uint32_t computeStageBindingOffset(DxbcProgramType stage) {
    return DxbcStageBindingCount * uint32_t(stage);
  }

  /**
   * \brief Computes first UAV binding index offset for a given stage
   *
   * \param [in] stage The shader stage
   * \returns Index of first UAV binding
   */
  inline uint32_t computeStageUavBindingOffset(DxbcProgramType stage) {
    return DxbcUavBindingIndex
         + DxbcUavBindingCount * (stage == DxbcProgramType::ComputeShader ? 2 : 0);
  }

  /**
   * \brief Computes constant buffer binding index
   *
   * \param [in] stage Shader stage
   * \param [in] index Constant buffer index
   * \returns Binding index
   */
  inline uint32_t computeConstantBufferBinding(DxbcProgramType stage, uint32_t index) {
    return computeStageBindingOffset(stage) + DxbcConstBufBindingIndex + index;
  }

  /**
   * \brief Computes sampler binding index
   *
   * \param [in] stage Shader stage
   * \param [in] index Sampler index
   * \returns Binding index
   */
  inline uint32_t computeSamplerBinding(DxbcProgramType stage, uint32_t index) {
    return computeStageBindingOffset(stage) + DxbcSamplerBindingIndex + index;
  }

  /**
   * \brief Computes resource binding index
   *
   * \param [in] stage Shader stage
   * \param [in] index Resource index
   * \returns Binding index
   */
  inline uint32_t computeSrvBinding(DxbcProgramType stage, uint32_t index) {
    return computeStageBindingOffset(stage) + DxbcResourceBindingIndex + index;
  }

  /**
   * \brief Computes UAV binding offset
   *
   * \param [in] stage Shader stage
   * \param [in] index UAV index
   * \returns Binding index
   */
  inline uint32_t computeUavBinding(DxbcProgramType stage, uint32_t index) {
    return computeStageUavBindingOffset(stage) + index;
  }

  /**
   * \brief Computes UAV counter binding offset
   *
   * \param [in] stage Shader stage
   * \param [in] index UAV index
   * \returns Binding index
   */
  inline uint32_t computeUavCounterBinding(DxbcProgramType stage, uint32_t index) {
    return computeStageUavBindingOffset(stage) + DxbcUavBindingCount + index;
  }

  /**
   * \brief Primitive vertex count
   *
   * Calculates the number of vertices
   * for a given primitive type.
   */
  uint32_t primitiveVertexCount(
          DxbcPrimitive   primitive);

}


code:
dxbc_src = files([
  'dxbc_analysis.cpp',
  'dxbc_chunk_isgn.cpp',
  'dxbc_chunk_shex.cpp',
  'dxbc_common.cpp',
  'dxbc_compiler.cpp',
  'dxbc_defs.cpp',
  'dxbc_decoder.cpp',
  'dxbc_header.cpp',
  'dxbc_module.cpp',
  'dxbc_names.cpp',
  'dxbc_options.cpp',
  'dxbc_reader.cpp',
  'dxbc_util.cpp',
])

dxbc_lib = static_library('dxbc', dxbc_src,
  include_directories : [ dxvk_include_path ],
)

dxbc_dep = declare_dependency(
  link_with           : [ dxbc_lib ],
  include_directories : [ dxvk_include_path ],
)


code:
LIBRARY DXGI.DLL
EXPORTS
    CreateDXGIFactory @9
    CreateDXGIFactory1 @10
    CreateDXGIFactory2 @11
    DXGIDeclareAdapterRemovalSupport @16
    DXGIGetDebugInterface1 @17


code:
#include <cstdlib>
#include <cstring>

#include <d3d10_1.h>

#include "dxgi_adapter.h"
#include "dxgi_enums.h"
#include "dxgi_factory.h"
#include "dxgi_format.h"
#include "dxgi_options.h"
#include "dxgi_output.h"

#include "../util/util_luid.h"

namespace dxvk {

  DxgiVkAdapter::DxgiVkAdapter(DxgiAdapter* pAdapter)
  : m_adapter(pAdapter) {

  }

  ULONG STDMETHODCALLTYPE DxgiVkAdapter::AddRef() {
    return m_adapter->AddRef();
  }

  ULONG STDMETHODCALLTYPE DxgiVkAdapter::Release() {
    return m_adapter->Release();
  }

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

  void STDMETHODCALLTYPE DxgiVkAdapter::GetVulkanHandles(
          VkInstance*               pInstance,
          VkPhysicalDevice*         pPhysDev) {
    auto adapter  = m_adapter->GetDXVKAdapter();
    auto instance = m_adapter->GetDXVKInstance();

    if (pInstance)
      *pInstance = instance->handle();

    if (pPhysDev)
      *pPhysDev = adapter->handle();
  }

  DxgiAdapter::DxgiAdapter(
          DxgiFactory*      factory,
    const Rc<DxvkAdapter>&  adapter,
          UINT              index)
  : m_factory (factory),
    m_adapter (adapter),
    m_interop (this),
    m_index   (index) {

  }

  DxgiAdapter::~DxgiAdapter() {
    if (m_eventThread.joinable()) {
      std::unique_lock<dxvk::mutex> lock(m_mutex);
      m_eventCookie = ~0u;
      m_cond.notify_one();

      lock.unlock();
      m_eventThread.join();
    }
  }

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

    *ppvObject = nullptr;

    if (riid == __uuidof(IUnknown)
     || riid == __uuidof(IDXGIObject)
     || riid == __uuidof(IDXGIAdapter)
     || riid == __uuidof(IDXGIAdapter1)
     || riid == __uuidof(IDXGIAdapter2)
     || riid == __uuidof(IDXGIAdapter3)
     || riid == __uuidof(IDXGIAdapter4)
     || riid == __uuidof(IDXGIDXVKAdapter)) {
      *ppvObject = ref(this);
      return S_OK;
    }

    if (riid == __uuidof(IDXGIVkInteropAdapter)) {
      *ppvObject = ref(&m_interop);
      return S_OK;
    }

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

  HRESULT STDMETHODCALLTYPE DxgiAdapter::GetParent(REFIID riid, void** ppParent) {
    return m_factory->QueryInterface(riid, ppParent);
  }

  HRESULT STDMETHODCALLTYPE DxgiAdapter::CheckInterfaceSupport(
          REFGUID                   InterfaceName,
          LARGE_INTEGER*            pUMDVersion) {
    HRESULT hr = DXGI_ERROR_UNSUPPORTED;

    if (InterfaceName == __uuidof(IDXGIDevice)
     || InterfaceName == __uuidof(ID3D10Device)
     || InterfaceName == __uuidof(ID3D10Device1))
      hr = S_OK;

    // We can't really reconstruct the version numbers
    // returned by Windows drivers from Vulkan data
    if (SUCCEEDED(hr) && pUMDVersion)
      pUMDVersion->QuadPart = ~0ull;

    if (FAILED(hr)) {
      Logger::err("DXGI: CheckInterfaceSupport: Unsupported interface");
      Logger::err(str::format(InterfaceName));
    }

    return hr;
  }

  HRESULT STDMETHODCALLTYPE DxgiAdapter::EnumOutputs(
          UINT                      Output,
          IDXGIOutput**             ppOutput) {
    InitReturnPtr(ppOutput);

    if (ppOutput == nullptr)
      return E_INVALIDARG;

    MonitorEnumInfo info;
    info.iMonitorId = Output;
    info.oMonitor   = nullptr;

    ::EnumDisplayMonitors(
      nullptr, nullptr, &MonitorEnumProc,
      reinterpret_cast<LPARAM>(&info));

    if (info.oMonitor == nullptr)
      return DXGI_ERROR_NOT_FOUND;

    *ppOutput = ref(new DxgiOutput(m_factory, this, info.oMonitor));
    return S_OK;
  }

  HRESULT STDMETHODCALLTYPE DxgiAdapter::GetDesc(DXGI_ADAPTER_DESC* pDesc) {
    if (pDesc == nullptr)
      return E_INVALIDARG;

    DXGI_ADAPTER_DESC3 desc;
    HRESULT hr = GetDesc3(&desc);

    if (SUCCEEDED(hr)) {
      std::memcpy(pDesc->Description, desc.Description, sizeof(pDesc->Description));

      pDesc->VendorId               = desc.VendorId;
      pDesc->DeviceId               = desc.DeviceId;
      pDesc->SubSysId               = desc.SubSysId;
      pDesc->Revision               = desc.Revision;
      pDesc->DedicatedVideoMemory   = desc.DedicatedVideoMemory;
      pDesc->DedicatedSystemMemory  = desc.DedicatedSystemMemory;
      pDesc->SharedSystemMemory     = desc.SharedSystemMemory;
      pDesc->AdapterLuid            = desc.AdapterLuid;
    }

    return hr;
  }

  HRESULT STDMETHODCALLTYPE DxgiAdapter::GetDesc1(DXGI_ADAPTER_DESC1* pDesc) {
    if (pDesc == nullptr)
      return E_INVALIDARG;

    DXGI_ADAPTER_DESC3 desc;
    HRESULT hr = GetDesc3(&desc);

    if (SUCCEEDED(hr)) {
      std::memcpy(pDesc->Description, desc.Description, sizeof(pDesc->Description));

      pDesc->VendorId               = desc.VendorId;
      pDesc->DeviceId               = desc.DeviceId;
      pDesc->SubSysId               = desc.SubSysId;
      pDesc->Revision               = desc.Revision;
      pDesc->DedicatedVideoMemory   = desc.DedicatedVideoMemory;
      pDesc->DedicatedSystemMemory  = desc.DedicatedSystemMemory;
      pDesc->SharedSystemMemory     = desc.SharedSystemMemory;
      pDesc->AdapterLuid            = desc.AdapterLuid;
      pDesc->Flags                  = desc.Flags;
    }

    return hr;
  }

  HRESULT STDMETHODCALLTYPE DxgiAdapter::GetDesc2(DXGI_ADAPTER_DESC2* pDesc) {
    if (pDesc == nullptr)
      return E_INVALIDARG;

    DXGI_ADAPTER_DESC3 desc;
    HRESULT hr = GetDesc3(&desc);

    if (SUCCEEDED(hr)) {
      std::memcpy(pDesc->Description, desc.Description, sizeof(pDesc->Description));

      pDesc->VendorId               = desc.VendorId;
      pDesc->DeviceId               = desc.DeviceId;
      pDesc->SubSysId               = desc.SubSysId;
      pDesc->Revision               = desc.Revision;
      pDesc->DedicatedVideoMemory   = desc.DedicatedVideoMemory;
      pDesc->DedicatedSystemMemory  = desc.DedicatedSystemMemory;
      pDesc->SharedSystemMemory     = desc.SharedSystemMemory;
      pDesc->AdapterLuid            = desc.AdapterLuid;
      pDesc->Flags                  = desc.Flags;
      pDesc->GraphicsPreemptionGranularity = desc.GraphicsPreemptionGranularity;
      pDesc->ComputePreemptionGranularity  = desc.ComputePreemptionGranularity;
    }

    return hr;
  }

  HRESULT STDMETHODCALLTYPE DxgiAdapter::GetDesc3(
          DXGI_ADAPTER_DESC3*       pDesc) {
    if (pDesc == nullptr)
      return E_INVALIDARG;

    const DxgiOptions* options = m_factory->GetOptions();

    auto deviceProp = m_adapter->deviceProperties();
    auto memoryProp = m_adapter->memoryProperties();
    auto deviceId   = m_adapter->devicePropertiesExt().coreDeviceId;

    // Custom Vendor / Device ID
    if (options->customVendorId >= 0)
      deviceProp.vendorID = options->customVendorId;

    if (options->customDeviceId >= 0)
      deviceProp.deviceID = options->customDeviceId;

    const char* description = deviceProp.deviceName;
    // Custom device description
    if (!options->customDeviceDesc.empty())
      description = options->customDeviceDesc.c_str();

    // XXX nvapi workaround for a lot of Unreal Engine 4 games
    if (options->customVendorId < 0 && options->customDeviceId < 0
     && options->nvapiHack && deviceProp.vendorID == uint16_t(DxvkGpuVendor::Nvidia)) {
      Logger::info("DXGI: NvAPI workaround enabled, reporting AMD GPU");
      deviceProp.vendorID = uint16_t(DxvkGpuVendor::Amd);
      deviceProp.deviceID = 0x67df; /* RX 480 */
    }

    // Convert device name
    std::memset(pDesc->Description, 0, sizeof(pDesc->Description));
    str::tows(description, pDesc->Description);

    // Get amount of video memory
    // based on the Vulkan heaps
    VkDeviceSize deviceMemory = 0;
    VkDeviceSize sharedMemory = 0;

    for (uint32_t i = 0; i < memoryProp.memoryHeapCount; i++) {
      VkMemoryHeap heap = memoryProp.memoryHeaps[i];

      if (heap.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)
        deviceMemory += heap.size;
      else
        sharedMemory += heap.size;
    }

    // Some games think we are on Intel given a lack of
    // NVAPI or AGS/atiadlxx support.
    // Report our device memory as shared memory,
    // and some small amount for the carveout.
    if (options->emulateUMA && !m_adapter->isUnifiedMemoryArchitecture()) {
      sharedMemory = deviceMemory;
      deviceMemory = 128 * (1 << 20);
    }

    // Some games are silly and need their memory limited
    if (options->maxDeviceMemory > 0
     && options->maxDeviceMemory < deviceMemory)
      deviceMemory = options->maxDeviceMemory;

    if (options->maxSharedMemory > 0
     && options->maxSharedMemory < sharedMemory)
      sharedMemory = options->maxSharedMemory;

    if (env::is32BitHostPlatform()) {
      // The value returned by DXGI is a 32-bit value
      // on 32-bit platforms, so we need to clamp it
      VkDeviceSize maxMemory = 0xC0000000;
      deviceMemory = std::min(deviceMemory, maxMemory);
      sharedMemory = std::min(sharedMemory, maxMemory);
    }

    pDesc->VendorId                       = deviceProp.vendorID;
    pDesc->DeviceId                       = deviceProp.deviceID;
    pDesc->SubSysId                       = 0;
    pDesc->Revision                       = 0;
    pDesc->DedicatedVideoMemory           = deviceMemory;
    pDesc->DedicatedSystemMemory          = 0;
    pDesc->SharedSystemMemory             = sharedMemory;
    pDesc->AdapterLuid                    = LUID { 0, 0 };
    pDesc->Flags                          = DXGI_ADAPTER_FLAG3_NONE;
    pDesc->GraphicsPreemptionGranularity  = DXGI_GRAPHICS_PREEMPTION_DMA_BUFFER_BOUNDARY;
    pDesc->ComputePreemptionGranularity   = DXGI_COMPUTE_PREEMPTION_DMA_BUFFER_BOUNDARY;

    if (deviceId.deviceLUIDValid)
      std::memcpy(&pDesc->AdapterLuid, deviceId.deviceLUID, VK_LUID_SIZE);
    else
      pDesc->AdapterLuid = GetAdapterLUID(m_index);

    return S_OK;
  }

  HRESULT STDMETHODCALLTYPE DxgiAdapter::QueryVideoMemoryInfo(
          UINT                          NodeIndex,
          DXGI_MEMORY_SEGMENT_GROUP     MemorySegmentGroup,
          DXGI_QUERY_VIDEO_MEMORY_INFO* pVideoMemoryInfo) {
    if (NodeIndex > 0 || !pVideoMemoryInfo)
      return E_INVALIDARG;

    if (MemorySegmentGroup != DXGI_MEMORY_SEGMENT_GROUP_LOCAL
     && MemorySegmentGroup != DXGI_MEMORY_SEGMENT_GROUP_NON_LOCAL)
      return E_INVALIDARG;

    DxvkAdapterMemoryInfo memInfo = m_adapter->getMemoryHeapInfo();

    VkMemoryHeapFlags heapFlagMask = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT;
    VkMemoryHeapFlags heapFlags    = 0;

    if (MemorySegmentGroup == DXGI_MEMORY_SEGMENT_GROUP_LOCAL)
      heapFlags |= VK_MEMORY_HEAP_DEVICE_LOCAL_BIT;

    pVideoMemoryInfo->Budget       = 0;
    pVideoMemoryInfo->CurrentUsage = 0;

    for (uint32_t i = 0; i < memInfo.heapCount; i++) {
      if ((memInfo.heaps[i].heapFlags & heapFlagMask) != heapFlags)
        continue;

      pVideoMemoryInfo->Budget       += memInfo.heaps[i].memoryBudget;
      pVideoMemoryInfo->CurrentUsage += memInfo.heaps[i].memoryAllocated;
    }

    // We don't implement reservation, but the observable
    // behaviour should match that of Windows drivers
    uint32_t segmentId = uint32_t(MemorySegmentGroup);

    pVideoMemoryInfo->AvailableForReservation = pVideoMemoryInfo->Budget / 2;
    pVideoMemoryInfo->CurrentReservation      = m_memReservation[segmentId];
    return S_OK;
  }

  HRESULT STDMETHODCALLTYPE DxgiAdapter::SetVideoMemoryReservation(
          UINT                          NodeIndex,
          DXGI_MEMORY_SEGMENT_GROUP     MemorySegmentGroup,
          UINT64                        Reservation) {
    DXGI_QUERY_VIDEO_MEMORY_INFO info;

    HRESULT hr = QueryVideoMemoryInfo(
      NodeIndex, MemorySegmentGroup, &info);

    if (FAILED(hr))
      return hr;

    if (Reservation > info.AvailableForReservation)
      return DXGI_ERROR_INVALID_CALL;

    uint32_t segmentId = uint32_t(MemorySegmentGroup);
    m_memReservation[segmentId] = Reservation;
    return S_OK;
  }

  HRESULT STDMETHODCALLTYPE DxgiAdapter::RegisterHardwareContentProtectionTeardownStatusEvent(
          HANDLE                        hEvent,
          DWORD*                        pdwCookie) {
    Logger::err("DxgiAdapter::RegisterHardwareContentProtectionTeardownStatusEvent: Not implemented");
    return E_NOTIMPL;
  }

  HRESULT STDMETHODCALLTYPE DxgiAdapter::RegisterVideoMemoryBudgetChangeNotificationEvent(
          HANDLE                        hEvent,
          DWORD*                        pdwCookie) {
    if (!hEvent || !pdwCookie)
      return DXGI_ERROR_INVALID_CALL;

    std::unique_lock<dxvk::mutex> lock(m_mutex);
    DWORD cookie = ++m_eventCookie;

    m_eventMap.insert({ cookie, hEvent });

    if (!m_eventThread.joinable())
      m_eventThread = dxvk::thread([this] { runEventThread(); });

    // This method seems to fire the
    // event immediately on Windows
    SetEvent(hEvent);

    *pdwCookie = cookie;
    return S_OK;
  }

  void STDMETHODCALLTYPE DxgiAdapter::UnregisterHardwareContentProtectionTeardownStatus(
          DWORD                         dwCookie) {
    Logger::err("DxgiAdapter::UnregisterHardwareContentProtectionTeardownStatus: Not implemented");
  }

  void STDMETHODCALLTYPE DxgiAdapter::UnregisterVideoMemoryBudgetChangeNotification(
          DWORD                         dwCookie) {
    std::unique_lock<dxvk::mutex> lock(m_mutex);
    m_eventMap.erase(dwCookie);
  }

  Rc<DxvkAdapter> STDMETHODCALLTYPE DxgiAdapter::GetDXVKAdapter() {
    return m_adapter;
  }

  Rc<DxvkInstance> STDMETHODCALLTYPE DxgiAdapter::GetDXVKInstance() {
    return m_factory->GetDXVKInstance();
  }

  void DxgiAdapter::runEventThread() {
    env::setThreadName(str::format("dxvk-adapter-", m_index));

    std::unique_lock<dxvk::mutex> lock(m_mutex);
    DxvkAdapterMemoryInfo memoryInfoOld = m_adapter->getMemoryHeapInfo();

    while (true) {
      m_cond.wait_for(lock, std::chrono::milliseconds(1500),
        [this] { return m_eventCookie == ~0u; });

      if (m_eventCookie == ~0u)
        return;

      auto memoryInfoNew = m_adapter->getMemoryHeapInfo();
      bool budgetChanged = false;

      for (uint32_t i = 0; i < memoryInfoNew.heapCount; i++) {
        budgetChanged |= memoryInfoNew.heaps[i].memoryBudget
                      != memoryInfoOld.heaps[i].memoryBudget;
      }

      if (budgetChanged) {
        memoryInfoOld = memoryInfoNew;

        for (const auto& pair : m_eventMap)
          SetEvent(pair.second);
      }
    }
  }

  BOOL CALLBACK DxgiAdapter::MonitorEnumProc(
          HMONITOR                  hmon,
          HDC                       hdc,
          LPRECT                    rect,
          LPARAM                    lp) {
    auto data = reinterpret_cast<MonitorEnumInfo*>(lp);

    if (data->iMonitorId--)
      return TRUE; /* continue */

    data->oMonitor = hmon;
    return FALSE; /* stop */
  }

}


code:
#pragma once

#include <mutex>
#include <unordered_map>

#include "dxgi_format.h"
#include "dxgi_interfaces.h"
#include "dxgi_output.h"

namespace dxvk {

  class DxgiAdapter;
  class DxgiFactory;
  class DxgiOutput;

  class DxgiVkAdapter : public IDXGIVkInteropAdapter {

  public:

    DxgiVkAdapter(DxgiAdapter* pAdapter);

    ULONG STDMETHODCALLTYPE AddRef();

    ULONG STDMETHODCALLTYPE Release();

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

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

  private:

    DxgiAdapter* m_adapter;

  };

  class DxgiAdapter : public DxgiObject<IDXGIDXVKAdapter> {

  public:

    DxgiAdapter(
            DxgiFactory*              factory,
      const Rc<DxvkAdapter>&          adapter,
            UINT                      index);

    ~DxgiAdapter();

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

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

    HRESULT STDMETHODCALLTYPE CheckInterfaceSupport(
            REFGUID                   InterfaceName,
            LARGE_INTEGER*            pUMDVersion) final;

    HRESULT STDMETHODCALLTYPE EnumOutputs(
            UINT                      Output,
            IDXGIOutput**             ppOutput) final;

    HRESULT STDMETHODCALLTYPE GetDesc(
            DXGI_ADAPTER_DESC*        pDesc) final;

    HRESULT STDMETHODCALLTYPE GetDesc1(
            DXGI_ADAPTER_DESC1*       pDesc) final;

    HRESULT STDMETHODCALLTYPE GetDesc2(
            DXGI_ADAPTER_DESC2*       pDesc) final;

    HRESULT STDMETHODCALLTYPE GetDesc3(
            DXGI_ADAPTER_DESC3*       pDesc) final;

    HRESULT STDMETHODCALLTYPE QueryVideoMemoryInfo(
            UINT                          NodeIndex,
            DXGI_MEMORY_SEGMENT_GROUP     MemorySegmentGroup,
            DXGI_QUERY_VIDEO_MEMORY_INFO* pVideoMemoryInfo) final;

    HRESULT STDMETHODCALLTYPE SetVideoMemoryReservation(
            UINT                          NodeIndex,
            DXGI_MEMORY_SEGMENT_GROUP     MemorySegmentGroup,
            UINT64                        Reservation) final;

    HRESULT STDMETHODCALLTYPE RegisterHardwareContentProtectionTeardownStatusEvent(
            HANDLE                        hEvent,
            DWORD*                        pdwCookie) final;

    HRESULT STDMETHODCALLTYPE RegisterVideoMemoryBudgetChangeNotificationEvent(
            HANDLE                        hEvent,
            DWORD*                        pdwCookie) final;

    void STDMETHODCALLTYPE UnregisterHardwareContentProtectionTeardownStatus(
            DWORD                         dwCookie) final;

    void STDMETHODCALLTYPE UnregisterVideoMemoryBudgetChangeNotification(
            DWORD                         dwCookie) final;

    Rc<DxvkAdapter> STDMETHODCALLTYPE GetDXVKAdapter() final;

    Rc<DxvkInstance> STDMETHODCALLTYPE GetDXVKInstance() final;

  private:

    Com<DxgiFactory>  m_factory;
    Rc<DxvkAdapter>   m_adapter;
    DxgiVkAdapter     m_interop;

    UINT              m_index;
    UINT64            m_memReservation[2] = { 0, 0 };

    dxvk::mutex                       m_mutex;
    dxvk::condition_variable          m_cond;

    DWORD                             m_eventCookie = 0;
    std::unordered_map<DWORD, HANDLE> m_eventMap;
    dxvk::thread                      m_eventThread;

    void runEventThread();

    struct MonitorEnumInfo {
      UINT      iMonitorId;
      HMONITOR  oMonitor;
    };

    static BOOL CALLBACK MonitorEnumProc(
            HMONITOR                  hmon,
            HDC                       hdc,
            LPRECT                    rect,
            LPARAM                    lp);

  };

}


code:
#include "dxgi_enums.h"

std::ostream& operator << (std::ostream& os, DXGI_FORMAT e) {
  switch (e) {
    ENUM_NAME(DXGI_FORMAT_UNKNOWN);
    ENUM_NAME(DXGI_FORMAT_R32G32B32A32_TYPELESS);
    ENUM_NAME(DXGI_FORMAT_R32G32B32A32_FLOAT);
    ENUM_NAME(DXGI_FORMAT_R32G32B32A32_UINT);
    ENUM_NAME(DXGI_FORMAT_R32G32B32A32_SINT);
    ENUM_NAME(DXGI_FORMAT_R32G32B32_TYPELESS);
    ENUM_NAME(DXGI_FORMAT_R32G32B32_FLOAT);
    ENUM_NAME(DXGI_FORMAT_R32G32B32_UINT);
    ENUM_NAME(DXGI_FORMAT_R32G32B32_SINT);
    ENUM_NAME(DXGI_FORMAT_R16G16B16A16_TYPELESS);
    ENUM_NAME(DXGI_FORMAT_R16G16B16A16_FLOAT);
    ENUM_NAME(DXGI_FORMAT_R16G16B16A16_UNORM);
    ENUM_NAME(DXGI_FORMAT_R16G16B16A16_UINT);
    ENUM_NAME(DXGI_FORMAT_R16G16B16A16_SNORM);
    ENUM_NAME(DXGI_FORMAT_R16G16B16A16_SINT);
    ENUM_NAME(DXGI_FORMAT_R32G32_TYPELESS);
    ENUM_NAME(DXGI_FORMAT_R32G32_FLOAT);
    ENUM_NAME(DXGI_FORMAT_R32G32_UINT);
    ENUM_NAME(DXGI_FORMAT_R32G32_SINT);
    ENUM_NAME(DXGI_FORMAT_R32G8X24_TYPELESS);
    ENUM_NAME(DXGI_FORMAT_D32_FLOAT_S8X24_UINT);
    ENUM_NAME(DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS);
    ENUM_NAME(DXGI_FORMAT_X32_TYPELESS_G8X24_UINT);
    ENUM_NAME(DXGI_FORMAT_R10G10B10A2_TYPELESS);
    ENUM_NAME(DXGI_FORMAT_R10G10B10A2_UNORM);
    ENUM_NAME(DXGI_FORMAT_R10G10B10A2_UINT);
    ENUM_NAME(DXGI_FORMAT_R11G11B10_FLOAT);
    ENUM_NAME(DXGI_FORMAT_R8G8B8A8_TYPELESS);
    ENUM_NAME(DXGI_FORMAT_R8G8B8A8_UNORM);
    ENUM_NAME(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB);
    ENUM_NAME(DXGI_FORMAT_R8G8B8A8_UINT);
    ENUM_NAME(DXGI_FORMAT_R8G8B8A8_SNORM);
    ENUM_NAME(DXGI_FORMAT_R8G8B8A8_SINT);
    ENUM_NAME(DXGI_FORMAT_R16G16_TYPELESS);
    ENUM_NAME(DXGI_FORMAT_R16G16_FLOAT);
    ENUM_NAME(DXGI_FORMAT_R16G16_UNORM);
    ENUM_NAME(DXGI_FORMAT_R16G16_UINT);
    ENUM_NAME(DXGI_FORMAT_R16G16_SNORM);
    ENUM_NAME(DXGI_FORMAT_R16G16_SINT);
    ENUM_NAME(DXGI_FORMAT_R32_TYPELESS);
    ENUM_NAME(DXGI_FORMAT_D32_FLOAT);
    ENUM_NAME(DXGI_FORMAT_R32_FLOAT);
    ENUM_NAME(DXGI_FORMAT_R32_UINT);
    ENUM_NAME(DXGI_FORMAT_R32_SINT);
    ENUM_NAME(DXGI_FORMAT_R24G8_TYPELESS);
    ENUM_NAME(DXGI_FORMAT_D24_UNORM_S8_UINT);
    ENUM_NAME(DXGI_FORMAT_R24_UNORM_X8_TYPELESS);
    ENUM_NAME(DXGI_FORMAT_X24_TYPELESS_G8_UINT);
    ENUM_NAME(DXGI_FORMAT_R8G8_TYPELESS);
    ENUM_NAME(DXGI_FORMAT_R8G8_UNORM);
    ENUM_NAME(DXGI_FORMAT_R8G8_UINT);
    ENUM_NAME(DXGI_FORMAT_R8G8_SNORM);
    ENUM_NAME(DXGI_FORMAT_R8G8_SINT);
    ENUM_NAME(DXGI_FORMAT_R16_TYPELESS);
    ENUM_NAME(DXGI_FORMAT_R16_FLOAT);
    ENUM_NAME(DXGI_FORMAT_D16_UNORM);
    ENUM_NAME(DXGI_FORMAT_R16_UNORM);
    ENUM_NAME(DXGI_FORMAT_R16_UINT);
    ENUM_NAME(DXGI_FORMAT_R16_SNORM);
    ENUM_NAME(DXGI_FORMAT_R16_SINT);
    ENUM_NAME(DXGI_FORMAT_R8_TYPELESS);
    ENUM_NAME(DXGI_FORMAT_R8_UNORM);
    ENUM_NAME(DXGI_FORMAT_R8_UINT);
    ENUM_NAME(DXGI_FORMAT_R8_SNORM);
    ENUM_NAME(DXGI_FORMAT_R8_SINT);
    ENUM_NAME(DXGI_FORMAT_A8_UNORM);
    ENUM_NAME(DXGI_FORMAT_R1_UNORM);
    ENUM_NAME(DXGI_FORMAT_R9G9B9E5_SHAREDEXP);
    ENUM_NAME(DXGI_FORMAT_R8G8_B8G8_UNORM);
    ENUM_NAME(DXGI_FORMAT_G8R8_G8B8_UNORM);
    ENUM_NAME(DXGI_FORMAT_BC1_TYPELESS);
    ENUM_NAME(DXGI_FORMAT_BC1_UNORM);
    ENUM_NAME(DXGI_FORMAT_BC1_UNORM_SRGB);
    ENUM_NAME(DXGI_FORMAT_BC2_TYPELESS);
    ENUM_NAME(DXGI_FORMAT_BC2_UNORM);
    ENUM_NAME(DXGI_FORMAT_BC2_UNORM_SRGB);
    ENUM_NAME(DXGI_FORMAT_BC3_TYPELESS);
    ENUM_NAME(DXGI_FORMAT_BC3_UNORM);
    ENUM_NAME(DXGI_FORMAT_BC3_UNORM_SRGB);
    ENUM_NAME(DXGI_FORMAT_BC4_TYPELESS);
    ENUM_NAME(DXGI_FORMAT_BC4_UNORM);
    ENUM_NAME(DXGI_FORMAT_BC4_SNORM);
    ENUM_NAME(DXGI_FORMAT_BC5_TYPELESS);
    ENUM_NAME(DXGI_FORMAT_BC5_UNORM);
    ENUM_NAME(DXGI_FORMAT_BC5_SNORM);
    ENUM_NAME(DXGI_FORMAT_B5G6R5_UNORM);
    ENUM_NAME(DXGI_FORMAT_B5G5R5A1_UNORM);
    ENUM_NAME(DXGI_FORMAT_B8G8R8A8_UNORM);
    ENUM_NAME(DXGI_FORMAT_B8G8R8X8_UNORM);
    ENUM_NAME(DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM);
    ENUM_NAME(DXGI_FORMAT_B8G8R8A8_TYPELESS);
    ENUM_NAME(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB);
    ENUM_NAME(DXGI_FORMAT_B8G8R8X8_TYPELESS);
    ENUM_NAME(DXGI_FORMAT_B8G8R8X8_UNORM_SRGB);
    ENUM_NAME(DXGI_FORMAT_BC6H_TYPELESS);
    ENUM_NAME(DXGI_FORMAT_BC6H_UF16);
    ENUM_NAME(DXGI_FORMAT_BC6H_SF16);
    ENUM_NAME(DXGI_FORMAT_BC7_TYPELESS);
    ENUM_NAME(DXGI_FORMAT_BC7_UNORM);
    ENUM_NAME(DXGI_FORMAT_BC7_UNORM_SRGB);
    ENUM_NAME(DXGI_FORMAT_AYUV);
    ENUM_NAME(DXGI_FORMAT_Y410);
    ENUM_NAME(DXGI_FORMAT_Y416);
    ENUM_NAME(DXGI_FORMAT_NV12);
    ENUM_NAME(DXGI_FORMAT_P010);
    ENUM_NAME(DXGI_FORMAT_P016);
    ENUM_NAME(DXGI_FORMAT_420_OPAQUE);
    ENUM_NAME(DXGI_FORMAT_YUY2);
    ENUM_NAME(DXGI_FORMAT_Y210);
    ENUM_NAME(DXGI_FORMAT_Y216);
    ENUM_NAME(DXGI_FORMAT_NV11);
    ENUM_NAME(DXGI_FORMAT_AI44);
    ENUM_NAME(DXGI_FORMAT_IA44);
    ENUM_NAME(DXGI_FORMAT_P8);
    ENUM_NAME(DXGI_FORMAT_A8P8);
    ENUM_NAME(DXGI_FORMAT_B4G4R4A4_UNORM);
    ENUM_DEFAULT(e);
  }
}


code:
#pragma once

#include "dxgi_include.h"

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


code:
#include "dxgi_factory.h"
#include "dxgi_swapchain.h"
#include "dxgi_swapchain_dispatcher.h"

namespace dxvk {

  DxgiFactory::DxgiFactory(UINT Flags)
  : m_instance    (new DxvkInstance()),
    m_monitorInfo (this),
    m_options     (m_instance->config()),
    m_flags       (Flags) {
    for (uint32_t i = 0; m_instance->enumAdapters(i) != nullptr; i++)
      m_instance->enumAdapters(i)->logAdapterInfo();
  }

  DxgiFactory::~DxgiFactory() {

  }

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

    *ppvObject = nullptr;

    if (riid == __uuidof(IUnknown)
     || riid == __uuidof(IDXGIObject)
     || riid == __uuidof(IDXGIFactory)
     || riid == __uuidof(IDXGIFactory1)
     || riid == __uuidof(IDXGIFactory2)
     || riid == __uuidof(IDXGIFactory3)
     || riid == __uuidof(IDXGIFactory4)
     || riid == __uuidof(IDXGIFactory5)
     || riid == __uuidof(IDXGIFactory6)
     || riid == __uuidof(IDXGIFactory7)) {
      *ppvObject = ref(this);
      return S_OK;
    }

    if (riid == __uuidof(IDXGIVkMonitorInfo)) {
      *ppvObject = ref(&m_monitorInfo);
      return S_OK;
    }

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

  HRESULT STDMETHODCALLTYPE DxgiFactory::GetParent(REFIID riid, void** ppParent) {
    InitReturnPtr(ppParent);

    Logger::warn("DxgiFactory::GetParent: Unknown interface query");
    return E_NOINTERFACE;
  }

  BOOL STDMETHODCALLTYPE DxgiFactory::IsWindowedStereoEnabled() {
    // We don't support Stereo 3D at the moment
    return FALSE;
  }

  HRESULT STDMETHODCALLTYPE DxgiFactory::CreateSoftwareAdapter(
          HMODULE         Module,
          IDXGIAdapter**  ppAdapter) {
    InitReturnPtr(ppAdapter);

    if (ppAdapter == nullptr)
      return DXGI_ERROR_INVALID_CALL;

    Logger::err("DXGI: CreateSoftwareAdapter: Software adapters not supported");
    return DXGI_ERROR_UNSUPPORTED;
  }

  HRESULT STDMETHODCALLTYPE DxgiFactory::CreateSwapChain(
          IUnknown*             pDevice,
          DXGI_SWAP_CHAIN_DESC* pDesc,
          IDXGISwapChain**      ppSwapChain) {
    if (ppSwapChain == nullptr || pDesc == nullptr || pDevice == nullptr)
      return DXGI_ERROR_INVALID_CALL;

    DXGI_SWAP_CHAIN_DESC1 desc;
    desc.Width              = pDesc->BufferDesc.Width;
    desc.Height             = pDesc->BufferDesc.Height;
    desc.Format             = pDesc->BufferDesc.Format;
    desc.Stereo             = FALSE;
    desc.SampleDesc         = pDesc->SampleDesc;
    desc.BufferUsage        = pDesc->BufferUsage;
    desc.BufferCount        = pDesc->BufferCount;
    desc.Scaling            = DXGI_SCALING_STRETCH;
    desc.SwapEffect         = pDesc->SwapEffect;
    desc.AlphaMode          = DXGI_ALPHA_MODE_IGNORE;
    desc.Flags              = pDesc->Flags;

    DXGI_SWAP_CHAIN_FULLSCREEN_DESC descFs;
    descFs.RefreshRate      = pDesc->BufferDesc.RefreshRate;
    descFs.ScanlineOrdering = pDesc->BufferDesc.ScanlineOrdering;
    descFs.Scaling          = pDesc->BufferDesc.Scaling;
    descFs.Windowed         = pDesc->Windowed;

    IDXGISwapChain1* swapChain = nullptr;
    HRESULT hr = CreateSwapChainForHwnd(
      pDevice, pDesc->OutputWindow,
      &desc, &descFs, nullptr,
      &swapChain);

    *ppSwapChain = swapChain;
    return hr;
  }

  HRESULT STDMETHODCALLTYPE DxgiFactory::CreateSwapChainForHwnd(
          IUnknown*             pDevice,
          HWND                  hWnd,
    const DXGI_SWAP_CHAIN_DESC1* pDesc,
    const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc,
          IDXGIOutput*          pRestrictToOutput,
          IDXGISwapChain1**     ppSwapChain) {
    InitReturnPtr(ppSwapChain);

    if (!ppSwapChain || !pDesc || !hWnd || !pDevice)
      return DXGI_ERROR_INVALID_CALL;

    Com<IWineDXGISwapChainFactory> wineDevice;

    if (SUCCEEDED(pDevice->QueryInterface(
          __uuidof(IWineDXGISwapChainFactory),
          reinterpret_cast<void**>(&wineDevice)))) {
      IDXGISwapChain4* frontendSwapChain;

      HRESULT hr = wineDevice->CreateSwapChainForHwnd(
        this, hWnd, pDesc, pFullscreenDesc,
        pRestrictToOutput, reinterpret_cast<IDXGISwapChain1**>(&frontendSwapChain));

      // No ref as that's handled by the object we're wrapping
      // which was ref'ed on creation.
      if (SUCCEEDED(hr))
        *ppSwapChain = new DxgiSwapChainDispatcher(frontendSwapChain);

      return hr;
    }

    Logger::err("DXGI: CreateSwapChainForHwnd: Unsupported device type");
    return DXGI_ERROR_UNSUPPORTED;
  }

  HRESULT STDMETHODCALLTYPE DxgiFactory::CreateSwapChainForCoreWindow(
          IUnknown*             pDevice,
          IUnknown*             pWindow,
    const DXGI_SWAP_CHAIN_DESC1* pDesc,
          IDXGIOutput*          pRestrictToOutput,
          IDXGISwapChain1**     ppSwapChain) {
    InitReturnPtr(ppSwapChain);

    Logger::err("DxgiFactory::CreateSwapChainForCoreWindow: Not implemented");
    return E_NOTIMPL;
  }

  HRESULT STDMETHODCALLTYPE DxgiFactory::CreateSwapChainForComposition(
          IUnknown*             pDevice,
    const DXGI_SWAP_CHAIN_DESC1* pDesc,
          IDXGIOutput*          pRestrictToOutput,
          IDXGISwapChain1**     ppSwapChain) {
    InitReturnPtr(ppSwapChain);

    Logger::err("DxgiFactory::CreateSwapChainForComposition: Not implemented");
    return E_NOTIMPL;
  }

  HRESULT STDMETHODCALLTYPE DxgiFactory::EnumAdapters(
          UINT            Adapter,
          IDXGIAdapter**  ppAdapter) {
    InitReturnPtr(ppAdapter);

    if (ppAdapter == nullptr)
      return DXGI_ERROR_INVALID_CALL;

    IDXGIAdapter1* handle = nullptr;
    HRESULT hr = this->EnumAdapters1(Adapter, &handle);
    *ppAdapter = handle;
    return hr;
  }

  HRESULT STDMETHODCALLTYPE DxgiFactory::EnumAdapters1(
          UINT            Adapter,
          IDXGIAdapter1** ppAdapter) {
    InitReturnPtr(ppAdapter);

    if (ppAdapter == nullptr)
      return DXGI_ERROR_INVALID_CALL;

    Rc<DxvkAdapter> dxvkAdapter
      = m_instance->enumAdapters(Adapter);

    if (dxvkAdapter == nullptr)
      return DXGI_ERROR_NOT_FOUND;

    *ppAdapter = ref(new DxgiAdapter(this, dxvkAdapter, Adapter));
    return S_OK;
  }

  HRESULT STDMETHODCALLTYPE DxgiFactory::EnumAdapterByLuid(
          LUID                  AdapterLuid,
          REFIID                riid,
          void**                ppvAdapter) {
    InitReturnPtr(ppvAdapter);
    uint32_t adapterId = 0;

    while (true) {
      Com<IDXGIAdapter> adapter;
      HRESULT hr = EnumAdapters(adapterId++, &adapter);

      if (FAILED(hr))
        return hr;

      DXGI_ADAPTER_DESC desc;
      adapter->GetDesc(&desc);

      if (!std::memcmp(&AdapterLuid, &desc.AdapterLuid, sizeof(LUID)))
        return adapter->QueryInterface(riid, ppvAdapter);
    }

    // This should be unreachable
    return DXGI_ERROR_NOT_FOUND;
  }

  HRESULT STDMETHODCALLTYPE DxgiFactory::EnumAdapterByGpuPreference(
          UINT                  Adapter,
          DXGI_GPU_PREFERENCE   GpuPreference,
          REFIID                riid,
          void**                ppvAdapter) {
    InitReturnPtr(ppvAdapter);
    uint32_t adapterCount = m_instance->adapterCount();

    if (Adapter >= adapterCount)
      return DXGI_ERROR_NOT_FOUND;

    // We know that the backend lists dedicated GPUs before
    // any integrated ones, so just list adapters in reverse
    // order. We have no other way to estimate performance.
    if (GpuPreference == DXGI_GPU_PREFERENCE_MINIMUM_POWER)
      Adapter = adapterCount - Adapter - 1;

    Com<IDXGIAdapter> adapter;
    HRESULT hr = this->EnumAdapters(Adapter, &adapter);

    if (FAILED(hr))
      return hr;

    return adapter->QueryInterface(riid, ppvAdapter);
  }

  HRESULT STDMETHODCALLTYPE DxgiFactory::EnumWarpAdapter(
          REFIID                riid,
          void**                ppvAdapter) {
    InitReturnPtr(ppvAdapter);

    static bool s_errorShown = false;

    if (!std::exchange(s_errorShown, true))
      Logger::warn("DxgiFactory::EnumWarpAdapter: WARP not supported, returning first hardware adapter");

    Com<IDXGIAdapter1> adapter;
    HRESULT hr = EnumAdapters1(0, &adapter);

    if (FAILED(hr))
      return hr;

    return adapter->QueryInterface(riid, ppvAdapter);
  }

  HRESULT STDMETHODCALLTYPE DxgiFactory::GetWindowAssociation(HWND *pWindowHandle) {
    if (pWindowHandle == nullptr)
      return DXGI_ERROR_INVALID_CALL;

    *pWindowHandle = m_associatedWindow;
    return S_OK;
  }

  HRESULT STDMETHODCALLTYPE DxgiFactory::GetSharedResourceAdapterLuid(
          HANDLE                hResource,
          LUID*                 pLuid) {
    Logger::err("DxgiFactory::GetSharedResourceAdapterLuid: Not implemented");
    return E_NOTIMPL;
  }

  HRESULT STDMETHODCALLTYPE DxgiFactory::MakeWindowAssociation(HWND WindowHandle, UINT Flags) {
    Logger::warn("DXGI: MakeWindowAssociation: Ignoring flags");
    m_associatedWindow = WindowHandle;
    return S_OK;
  }

  BOOL STDMETHODCALLTYPE DxgiFactory::IsCurrent() {
    return TRUE;
  }

  HRESULT STDMETHODCALLTYPE DxgiFactory::RegisterOcclusionStatusWindow(
          HWND                  WindowHandle,
          UINT                  wMsg,
          DWORD*                pdwCookie) {
    Logger::err("DxgiFactory::RegisterOcclusionStatusWindow: Not implemented");
    return E_NOTIMPL;
  }

  HRESULT STDMETHODCALLTYPE DxgiFactory::RegisterStereoStatusEvent(
          HANDLE                hEvent,
          DWORD*                pdwCookie) {
    Logger::err("DxgiFactory::RegisterStereoStatusEvent: Not implemented");
    return E_NOTIMPL;
  }

  HRESULT STDMETHODCALLTYPE DxgiFactory::RegisterStereoStatusWindow(
          HWND                  WindowHandle,
          UINT                  wMsg,
          DWORD*                pdwCookie) {
    Logger::err("DxgiFactory::RegisterStereoStatusWindow: Not implemented");
    return E_NOTIMPL;
  }

  HRESULT STDMETHODCALLTYPE DxgiFactory::RegisterOcclusionStatusEvent(
          HANDLE                hEvent,
          DWORD*                pdwCookie) {
    Logger::err("DxgiFactory::RegisterOcclusionStatusEvent: Not implemented");
    return E_NOTIMPL;
  }

  void STDMETHODCALLTYPE DxgiFactory::UnregisterStereoStatus(
          DWORD                 dwCookie) {
    Logger::err("DxgiFactory::UnregisterStereoStatus: Not implemented");
  }

  void STDMETHODCALLTYPE DxgiFactory::UnregisterOcclusionStatus(
          DWORD                 dwCookie) {
    Logger::err("DxgiFactory::UnregisterOcclusionStatus: Not implemented");
  }

  UINT STDMETHODCALLTYPE DxgiFactory::GetCreationFlags() {
    return m_flags;
  }

  HRESULT STDMETHODCALLTYPE DxgiFactory::CheckFeatureSupport(
          DXGI_FEATURE          Feature,
          void*                 pFeatureSupportData,
          UINT                  FeatureSupportDataSize) {
    switch (Feature) {
      case DXGI_FEATURE_PRESENT_ALLOW_TEARING: {
        auto info = static_cast<BOOL*>(pFeatureSupportData);

        if (FeatureSupportDataSize != sizeof(*info))
          return E_INVALIDARG;

        *info = TRUE;
      } return S_OK;

      default:
        Logger::err(str::format("DxgiFactory: CheckFeatureSupport: Unknown feature: ", uint32_t(Feature)));
        return E_INVALIDARG;
    }
  }

  HRESULT STDMETHODCALLTYPE DxgiFactory::RegisterAdaptersChangedEvent(
          HANDLE                hEvent,
          DWORD*                pdwCookie) {
    Logger::err("DxgiFactory: RegisterAdaptersChangedEvent: Stub");
    return E_NOTIMPL;
  }

  HRESULT STDMETHODCALLTYPE DxgiFactory::UnregisterAdaptersChangedEvent(
          DWORD                 Cookie) {
    Logger::err("DxgiFactory: UnregisterAdaptersChangedEvent: Stub");
    return E_NOTIMPL;
  }

}


code:
#pragma once

#include <vector>

#include "dxgi_adapter.h"
#include "dxgi_monitor.h"
#include "dxgi_options.h"

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

namespace dxvk {

  class DxgiFactory : public DxgiObject<IDXGIFactory7> {

  public:

    DxgiFactory(UINT Flags);
    ~DxgiFactory();

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

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

    BOOL STDMETHODCALLTYPE IsWindowedStereoEnabled() final;

    HRESULT STDMETHODCALLTYPE CreateSoftwareAdapter(
            HMODULE               Module,
            IDXGIAdapter**        ppAdapter) final;

    HRESULT STDMETHODCALLTYPE CreateSwapChain(
            IUnknown*             pDevice,
            DXGI_SWAP_CHAIN_DESC* pDesc,
            IDXGISwapChain**      ppSwapChain) final;

    HRESULT STDMETHODCALLTYPE CreateSwapChainForHwnd(
            IUnknown*             pDevice,
            HWND                  hWnd,
      const DXGI_SWAP_CHAIN_DESC1* pDesc,
      const DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pFullscreenDesc,
            IDXGIOutput*          pRestrictToOutput,
            IDXGISwapChain1**     ppSwapChain) final;

    HRESULT STDMETHODCALLTYPE CreateSwapChainForCoreWindow(
            IUnknown*             pDevice,
            IUnknown*             pWindow,
      const DXGI_SWAP_CHAIN_DESC1* pDesc,
            IDXGIOutput*          pRestrictToOutput,
            IDXGISwapChain1**     ppSwapChain) final;

    HRESULT STDMETHODCALLTYPE CreateSwapChainForComposition(
            IUnknown*             pDevice,
      const DXGI_SWAP_CHAIN_DESC1* pDesc,
            IDXGIOutput*          pRestrictToOutput,
            IDXGISwapChain1**     ppSwapChain) final;

    HRESULT STDMETHODCALLTYPE EnumAdapters(
            UINT                  Adapter,
            IDXGIAdapter**        ppAdapter) final;

    HRESULT STDMETHODCALLTYPE EnumAdapters1(
            UINT                  Adapter,
            IDXGIAdapter1**       ppAdapter) final;

    HRESULT STDMETHODCALLTYPE EnumAdapterByLuid(
            LUID                  AdapterLuid,
            REFIID                riid,
            void**                ppvAdapter) final;

    HRESULT STDMETHODCALLTYPE EnumAdapterByGpuPreference(
            UINT                  Adapter,
            DXGI_GPU_PREFERENCE   GpuPreference,
            REFIID                riid,
            void**                ppvAdapter);

    HRESULT STDMETHODCALLTYPE EnumWarpAdapter(
            REFIID                riid,
            void**                ppvAdapter) final;

    HRESULT STDMETHODCALLTYPE GetWindowAssociation(
            HWND*                 pWindowHandle) final;

    HRESULT STDMETHODCALLTYPE GetSharedResourceAdapterLuid(
            HANDLE                hResource,
            LUID*                 pLuid) final;

    HRESULT STDMETHODCALLTYPE MakeWindowAssociation(
            HWND                  WindowHandle,
            UINT                  Flags) final;

    BOOL STDMETHODCALLTYPE IsCurrent() final;

    HRESULT STDMETHODCALLTYPE RegisterOcclusionStatusWindow(
            HWND                  WindowHandle,
            UINT                  wMsg,
            DWORD*                pdwCookie) final;

    HRESULT STDMETHODCALLTYPE RegisterStereoStatusEvent(
            HANDLE                hEvent,
            DWORD*                pdwCookie) final;

    HRESULT STDMETHODCALLTYPE RegisterStereoStatusWindow(
            HWND                  WindowHandle,
            UINT                  wMsg,
            DWORD*                pdwCookie) final;

    HRESULT STDMETHODCALLTYPE RegisterOcclusionStatusEvent(
            HANDLE                hEvent,
            DWORD*                pdwCookie) final;

    void STDMETHODCALLTYPE UnregisterStereoStatus(
            DWORD                 dwCookie) final;

    void STDMETHODCALLTYPE UnregisterOcclusionStatus(
            DWORD                 dwCookie) final;

    UINT STDMETHODCALLTYPE GetCreationFlags() final;

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

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

    HRESULT STDMETHODCALLTYPE UnregisterAdaptersChangedEvent(
            DWORD                 Cookie);

    Rc<DxvkInstance> GetDXVKInstance() const {
      return m_instance;
    }

    const DxgiOptions* GetOptions() const {
      return &m_options;
    }

    DxgiMonitorInfo* GetMonitorInfo() {
      return &m_monitorInfo;
    }

  private:

    Rc<DxvkInstance> m_instance;
    DxgiMonitorInfo  m_monitorInfo;
    DxgiOptions      m_options;
    UINT             m_flags;

    HWND m_associatedWindow = nullptr;

  };

}


code:
#include "dxgi_format.h"

#include <array>

namespace dxvk {

  const std::array<DXGI_VK_FORMAT_MAPPING, 133> g_dxgiFormats = {{
    // DXGI_FORMAT_UNKNOWN
    { },
    // DXGI_FORMAT_R32G32B32A32_TYPELESS
    { VK_FORMAT_R32G32B32A32_UINT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R32G32B32A32_UINT },
    // DXGI_FORMAT_R32G32B32A32_FLOAT
    { VK_FORMAT_R32G32B32A32_SFLOAT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R32G32B32A32_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R32G32B32A32_UINT
    { VK_FORMAT_R32G32B32A32_UINT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R32G32B32A32_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R32G32B32A32_SINT
    { VK_FORMAT_R32G32B32A32_SINT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R32G32B32A32_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R32G32B32_TYPELESS
    { VK_FORMAT_R32G32B32_UINT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R32G32B32_UINT },
    // DXGI_FORMAT_R32G32B32_FLOAT
    { VK_FORMAT_R32G32B32_SFLOAT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R32G32B32_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R32G32B32_UINT
    { VK_FORMAT_R32G32B32_UINT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R32G32B32_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R32G32B32_SINT
    { VK_FORMAT_R32G32B32_SINT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R32G32B32_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R16G16B16A16_TYPELESS
    { VK_FORMAT_R16G16B16A16_UNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R16G16B16A16_UINT },
    // DXGI_FORMAT_R16G16B16A16_FLOAT
    { VK_FORMAT_R16G16B16A16_SFLOAT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R16G16B16A16_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R16G16B16A16_UNORM
    { VK_FORMAT_R16G16B16A16_UNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R16G16B16A16_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R16G16B16A16_UINT
    { VK_FORMAT_R16G16B16A16_UINT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R16G16B16A16_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R16G16B16A16_SNORM
    { VK_FORMAT_R16G16B16A16_SNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R16G16B16A16_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R16G16B16A16_SINT
    { VK_FORMAT_R16G16B16A16_SINT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R16G16B16A16_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R32G32_TYPELESS
    { VK_FORMAT_R32G32_UINT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R32G32_UINT },
    // DXGI_FORMAT_R32G32_FLOAT
    { VK_FORMAT_R32G32_SFLOAT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R32G32_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R32G32_UINT
    { VK_FORMAT_R32G32_UINT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R32G32_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R32G32_SINT
    { VK_FORMAT_R32G32_SINT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R32G32_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R32G8X24_TYPELESS
    { VK_FORMAT_UNDEFINED,
      VK_FORMAT_D32_SFLOAT_S8_UINT,
      VK_FORMAT_UNDEFINED },
    // DXGI_FORMAT_D32_FLOAT_S8X24_UINT
    { VK_FORMAT_UNDEFINED,
      VK_FORMAT_D32_SFLOAT_S8_UINT,
      VK_FORMAT_UNDEFINED,
      0, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT },
    // DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS
    { VK_FORMAT_UNDEFINED,
      VK_FORMAT_D32_SFLOAT_S8_UINT,
      VK_FORMAT_UNDEFINED,
      0, VK_IMAGE_ASPECT_DEPTH_BIT },
    // DXGI_FORMAT_X32_TYPELESS_G8X24_UINT
    { VK_FORMAT_UNDEFINED,
      VK_FORMAT_D32_SFLOAT_S8_UINT,
      VK_FORMAT_UNDEFINED,
      0, VK_IMAGE_ASPECT_STENCIL_BIT },
    // DXGI_FORMAT_R10G10B10A2_TYPELESS
    { VK_FORMAT_A2B10G10R10_UNORM_PACK32,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_A2B10G10R10_UINT_PACK32 },
    // DXGI_FORMAT_R10G10B10A2_UNORM
    { VK_FORMAT_A2B10G10R10_UNORM_PACK32,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_A2B10G10R10_UINT_PACK32,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R10G10B10A2_UINT
    { VK_FORMAT_A2B10G10R10_UINT_PACK32,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_A2B10G10R10_UINT_PACK32,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R11G11B10_FLOAT
    { VK_FORMAT_B10G11R11_UFLOAT_PACK32,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R32_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R8G8B8A8_TYPELESS
    { VK_FORMAT_R8G8B8A8_UNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R8G8B8A8_UINT },
    // DXGI_FORMAT_R8G8B8A8_UNORM
    { VK_FORMAT_R8G8B8A8_UNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R8G8B8A8_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
    { VK_FORMAT_R8G8B8A8_SRGB,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R8G8B8A8_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R8G8B8A8_UINT
    { VK_FORMAT_R8G8B8A8_UINT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R8G8B8A8_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R8G8B8A8_SNORM
    { VK_FORMAT_R8G8B8A8_SNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R8G8B8A8_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R8G8B8A8_SINT
    { VK_FORMAT_R8G8B8A8_SINT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R8G8B8A8_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R16G16_TYPELESS
    { VK_FORMAT_R16G16_UNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R16G16_UINT },
    // DXGI_FORMAT_R16G16_FLOAT
    { VK_FORMAT_R16G16_SFLOAT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R16G16_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R16G16_UNORM
    { VK_FORMAT_R16G16_UNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R16G16_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R16G16_UINT
    { VK_FORMAT_R16G16_UINT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R16G16_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R16G16_SNORM
    { VK_FORMAT_R16G16_SNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R16G16_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R16G16_SINT
    { VK_FORMAT_R16G16_SINT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R16G16_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R32_TYPELESS
    { VK_FORMAT_R32_UINT,
      VK_FORMAT_D32_SFLOAT,
      VK_FORMAT_R32_UINT },
    // DXGI_FORMAT_D32_FLOAT
    { VK_FORMAT_UNDEFINED,
      VK_FORMAT_D32_SFLOAT,
      VK_FORMAT_UNDEFINED,
      0, VK_IMAGE_ASPECT_DEPTH_BIT },
    // DXGI_FORMAT_R32_FLOAT
    { VK_FORMAT_R32_SFLOAT,
      VK_FORMAT_D32_SFLOAT,
      VK_FORMAT_R32_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT,
      VK_IMAGE_ASPECT_DEPTH_BIT },
    // DXGI_FORMAT_R32_UINT
    { VK_FORMAT_R32_UINT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R32_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R32_SINT
    { VK_FORMAT_R32_SINT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R32_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R24G8_TYPELESS
    { VK_FORMAT_UNDEFINED,
      VK_FORMAT_D24_UNORM_S8_UINT,
      VK_FORMAT_UNDEFINED },
    // DXGI_FORMAT_D24_UNORM_S8_UINT
    { VK_FORMAT_UNDEFINED,
      VK_FORMAT_D24_UNORM_S8_UINT,
      VK_FORMAT_UNDEFINED,
      0, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT },
    // DXGI_FORMAT_R24_UNORM_X8_TYPELESS
    { VK_FORMAT_UNDEFINED,
      VK_FORMAT_D24_UNORM_S8_UINT,
      VK_FORMAT_UNDEFINED,
      0, VK_IMAGE_ASPECT_DEPTH_BIT },
    // DXGI_FORMAT_X24_TYPELESS_G8_UINT
    { VK_FORMAT_UNDEFINED,
      VK_FORMAT_D24_UNORM_S8_UINT,
      VK_FORMAT_UNDEFINED,
      0, VK_IMAGE_ASPECT_STENCIL_BIT },
    // DXGI_FORMAT_R8G8_TYPELESS
    { VK_FORMAT_R8G8_UNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R8G8_UINT },
    // DXGI_FORMAT_R8G8_UNORM
    { VK_FORMAT_R8G8_UNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R8G8_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R8G8_UINT
    { VK_FORMAT_R8G8_UINT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R8G8_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R8G8_SNORM
    { VK_FORMAT_R8G8_SNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R8G8_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R8G8_SINT
    { VK_FORMAT_R8G8_SINT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R8G8_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R16_TYPELESS
    { VK_FORMAT_R16_UNORM,
      VK_FORMAT_D16_UNORM,
      VK_FORMAT_R16_UINT },
    // DXGI_FORMAT_R16_FLOAT
    { VK_FORMAT_R16_SFLOAT,
      VK_FORMAT_D16_UNORM,
      VK_FORMAT_R16_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT,
      VK_IMAGE_ASPECT_DEPTH_BIT },
    // DXGI_FORMAT_D16_UNORM
    { VK_FORMAT_UNDEFINED,
      VK_FORMAT_D16_UNORM,
      VK_FORMAT_UNDEFINED,
      0, VK_IMAGE_ASPECT_DEPTH_BIT },
    // DXGI_FORMAT_R16_UNORM
    { VK_FORMAT_R16_UNORM,
      VK_FORMAT_D16_UNORM,
      VK_FORMAT_R16_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT,
      VK_IMAGE_ASPECT_DEPTH_BIT },
    // DXGI_FORMAT_R16_UINT
    { VK_FORMAT_R16_UINT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R16_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R16_SNORM
    { VK_FORMAT_R16_SNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R16_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R16_SINT
    { VK_FORMAT_R16_SINT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R16_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R8_TYPELESS
    { VK_FORMAT_R8_UNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R8_UINT },
    // DXGI_FORMAT_R8_UNORM
    { VK_FORMAT_R8_UNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R8_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R8_UINT
    { VK_FORMAT_R8_UINT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R8_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R8_SNORM
    { VK_FORMAT_R8_SNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R8_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R8_SINT
    { VK_FORMAT_R8_SINT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R8_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_A8_UNORM
    { VK_FORMAT_R8_UNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT, 0,
      { VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_ZERO,
        VK_COMPONENT_SWIZZLE_ZERO, VK_COMPONENT_SWIZZLE_R }},
    // DXGI_FORMAT_R1_UNORM
    { }, // Unsupported
    // DXGI_FORMAT_R9G9B9E5_SHAREDEXP
    { VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_R8G8_B8G8_UNORM
    { VK_FORMAT_B8G8R8G8_422_UNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_G8R8_G8B8_UNORM
    { VK_FORMAT_G8B8G8R8_422_UNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_BC1_TYPELESS
    { VK_FORMAT_BC1_RGBA_UNORM_BLOCK,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED },
    // DXGI_FORMAT_BC1_UNORM
    { VK_FORMAT_BC1_RGBA_UNORM_BLOCK,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_BC1_UNORM_SRGB
    { VK_FORMAT_BC1_RGBA_SRGB_BLOCK,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_BC2_TYPELESS
    { VK_FORMAT_BC2_UNORM_BLOCK,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED },
    // DXGI_FORMAT_BC2_UNORM
    { VK_FORMAT_BC2_UNORM_BLOCK,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_BC2_UNORM_SRGB
    { VK_FORMAT_BC2_SRGB_BLOCK,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_BC3_TYPELESS
    { VK_FORMAT_BC3_UNORM_BLOCK,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED },
    // DXGI_FORMAT_BC3_UNORM
    { VK_FORMAT_BC3_UNORM_BLOCK,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_BC3_UNORM_SRGB
    { VK_FORMAT_BC3_SRGB_BLOCK,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_BC4_TYPELESS
    { VK_FORMAT_BC4_UNORM_BLOCK,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED },
    // DXGI_FORMAT_BC4_UNORM
    { VK_FORMAT_BC4_UNORM_BLOCK,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_BC4_SNORM
    { VK_FORMAT_BC4_SNORM_BLOCK,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_BC5_TYPELESS
    { VK_FORMAT_BC5_UNORM_BLOCK,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED },
    // DXGI_FORMAT_BC5_UNORM
    { VK_FORMAT_BC5_UNORM_BLOCK,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_BC5_SNORM
    { VK_FORMAT_BC5_SNORM_BLOCK,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_B5G6R5_UNORM
    { VK_FORMAT_R5G6B5_UNORM_PACK16,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_B5G5R5A1_UNORM
    { VK_FORMAT_A1R5G5B5_UNORM_PACK16,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_B8G8R8A8_UNORM
    { VK_FORMAT_B8G8R8A8_UNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_B8G8R8X8_UNORM
    { VK_FORMAT_B8G8R8A8_UNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT, 0,
      { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
        VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_ONE }},
    // DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM
    { }, // Unsupported
    // DXGI_FORMAT_B8G8R8A8_TYPELESS
    { VK_FORMAT_B8G8R8A8_UNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED },
    // DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
    { VK_FORMAT_B8G8R8A8_SRGB,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_B8G8R8X8_TYPELESS
    { VK_FORMAT_B8G8R8A8_UNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_B8G8R8X8_UNORM_SRGB
    { VK_FORMAT_B8G8R8A8_SRGB,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT, 0,
      { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
        VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_ONE }},
    // DXGI_FORMAT_BC6H_TYPELESS
    { VK_FORMAT_BC6H_UFLOAT_BLOCK,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED },
    // DXGI_FORMAT_BC6H_UF16
    { VK_FORMAT_BC6H_UFLOAT_BLOCK,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_BC6H_SF16
    { VK_FORMAT_BC6H_SFLOAT_BLOCK,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_BC7_TYPELESS
    { VK_FORMAT_BC7_UNORM_BLOCK,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED },
    // DXGI_FORMAT_BC7_UNORM
    { VK_FORMAT_BC7_UNORM_BLOCK,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_BC7_UNORM_SRGB
    { VK_FORMAT_BC7_SRGB_BLOCK,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_AYUV
    { VK_FORMAT_R8G8B8A8_UNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_R8G8B8A8_UINT,
      VK_IMAGE_ASPECT_COLOR_BIT, 0,
      { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_B,
        VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_A } },
    // DXGI_FORMAT_Y410
    { }, // Unsupported
    // DXGI_FORMAT_Y416
    { }, // Unsupported
    // DXGI_FORMAT_NV12
    { VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT },
    // DXGI_FORMAT_P010
    { }, // Unsupported
    // DXGI_FORMAT_P016
    { }, // Unsupported
    // DXGI_FORMAT_420_OPAQUE
    { VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_PLANE_0_BIT | VK_IMAGE_ASPECT_PLANE_1_BIT },
    // DXGI_FORMAT_YUY2
    { VK_FORMAT_G8B8G8R8_422_UNORM,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_Y210
    { }, // Unsupported
    // DXGI_FORMAT_Y216
    { }, // Unsupported
    // DXGI_FORMAT_NV11
    { }, // Unsupported
    // DXGI_FORMAT_AI44
    { }, // Unsupported
    // DXGI_FORMAT_IA44
    { }, // Unsupported
    // DXGI_FORMAT_P8
    { }, // Unsupported
    // DXGI_FORMAT_A8P8
    { }, // Unsupported
    // DXGI_FORMAT_B4G4R4A4_UNORM
    { VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT,
      VK_FORMAT_UNDEFINED,
      VK_FORMAT_UNDEFINED,
      VK_IMAGE_ASPECT_COLOR_BIT },
    // DXGI_FORMAT_P208
    { }, // Unsupported
    // DXGI_FORMAT_V208
    { }, // Unsupported
    // DXGI_FORMAT_V408
    { }, // Unsupported
  }};

  const std::array<DXGI_VK_FORMAT_FAMILY, 133> g_dxgiFamilies = {{
    // DXGI_FORMAT_UNKNOWN
    { },
    // DXGI_FORMAT_R32G32B32A32_TYPELESS
    { VK_FORMAT_R32G32B32A32_UINT,
      VK_FORMAT_R32G32B32A32_SINT,
      VK_FORMAT_R32G32B32A32_SFLOAT },
    // DXGI_FORMAT_R32G32B32A32_FLOAT
    { },
    // DXGI_FORMAT_R32G32B32A32_UINT
    { },
    // DXGI_FORMAT_R32G32B32A32_SINT
    { },
    // DXGI_FORMAT_R32G32B32_TYPELESS
    { VK_FORMAT_R32G32B32_UINT,
      VK_FORMAT_R32G32B32_SINT,
      VK_FORMAT_R32G32B32_SFLOAT },
    // DXGI_FORMAT_R32G32B32_FLOAT
    { },
    // DXGI_FORMAT_R32G32B32_UINT
    { },
    // DXGI_FORMAT_R32G32B32_SINT
    { },
    // DXGI_FORMAT_R16G16B16A16_TYPELESS
    { VK_FORMAT_R16G16B16A16_UNORM,
      VK_FORMAT_R16G16B16A16_SNORM,
      VK_FORMAT_R16G16B16A16_UINT,
      VK_FORMAT_R16G16B16A16_SINT,
      VK_FORMAT_R16G16B16A16_SFLOAT },
    // DXGI_FORMAT_R16G16B16A16_FLOAT
    { },
    // DXGI_FORMAT_R16G16B16A16_UNORM
    { },
    // DXGI_FORMAT_R16G16B16A16_UINT
    { },
    // DXGI_FORMAT_R16G16B16A16_SNORM
    { },
    // DXGI_FORMAT_R16G16B16A16_SINT
    { },
    // DXGI_FORMAT_R32G32_TYPELESS
    { VK_FORMAT_R32G32_UINT,
      VK_FORMAT_R32G32_SINT,
      VK_FORMAT_R32G32_SFLOAT },
    // DXGI_FORMAT_R32G32_FLOAT
    { },
    // DXGI_FORMAT_R32G32_UINT
    { },
    // DXGI_FORMAT_R32G32_SINT
    { },
    // DXGI_FORMAT_R32G8X24_TYPELESS
    { },
    // DXGI_FORMAT_D32_FLOAT_S8X24_UINT
    { },
    // DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS
    { },
    // DXGI_FORMAT_X32_TYPELESS_G8X24_UINT
    { },
    // DXGI_FORMAT_R10G10B10A2_TYPELESS
    { VK_FORMAT_A2B10G10R10_UNORM_PACK32,
      VK_FORMAT_A2B10G10R10_UINT_PACK32 },
    // DXGI_FORMAT_R10G10B10A2_UNORM
    { },
    // DXGI_FORMAT_R10G10B10A2_UINT
    { },
    // DXGI_FORMAT_R11G11B10_FLOAT
    { },
    // DXGI_FORMAT_R8G8B8A8_TYPELESS
    { VK_FORMAT_R8G8B8A8_UNORM,
      VK_FORMAT_R8G8B8A8_SNORM,
      VK_FORMAT_R8G8B8A8_SRGB,
      VK_FORMAT_R8G8B8A8_UINT,
      VK_FORMAT_R8G8B8A8_SINT },
    // DXGI_FORMAT_R8G8B8A8_UNORM
    { VK_FORMAT_R8G8B8A8_UNORM,
      VK_FORMAT_R8G8B8A8_SRGB },
    // DXGI_FORMAT_R8G8B8A8_UNORM_SRGB
    { VK_FORMAT_R8G8B8A8_UNORM,
      VK_FORMAT_R8G8B8A8_SRGB },
    // DXGI_FORMAT_R8G8B8A8_UINT
    { },
    // DXGI_FORMAT_R8G8B8A8_SNORM
    { },
    // DXGI_FORMAT_R8G8B8A8_SINT
    { },
    // DXGI_FORMAT_R16G16_TYPELESS
    { VK_FORMAT_R16G16_UNORM,
      VK_FORMAT_R16G16_SNORM,
      VK_FORMAT_R16G16_UINT,
      VK_FORMAT_R16G16_SINT,
      VK_FORMAT_R16G16_SFLOAT },
    // DXGI_FORMAT_R16G16_FLOAT
    { },
    // DXGI_FORMAT_R16G16_UNORM
    { },
    // DXGI_FORMAT_R16G16_UINT
    { },
    // DXGI_FORMAT_R16G16_SNORM
    { },
    // DXGI_FORMAT_R16G16_SINT
    { },
    // DXGI_FORMAT_R32_TYPELESS
    { VK_FORMAT_R32_UINT,
      VK_FORMAT_R32_SINT,
      VK_FORMAT_R32_SFLOAT },
    // DXGI_FORMAT_D32_FLOAT
    { },
    // DXGI_FORMAT_R32_FLOAT
    { },
    // DXGI_FORMAT_R32_UINT
    { },
    // DXGI_FORMAT_R32_SINT
    { },
    // DXGI_FORMAT_R24G8_TYPELESS
    { },
    // DXGI_FORMAT_D24_UNORM_S8_UINT
    { },
    // DXGI_FORMAT_R24_UNORM_X8_TYPELESS
    { },
    // DXGI_FORMAT_X24_TYPELESS_G8_UINT
    { },
    // DXGI_FORMAT_R8G8_TYPELESS
    { VK_FORMAT_R8G8_UNORM,
      VK_FORMAT_R8G8_SNORM,
      VK_FORMAT_R8G8_UINT,
      VK_FORMAT_R8G8_SINT },
    // DXGI_FORMAT_R8G8_UNORM
    { },
    // DXGI_FORMAT_R8G8_UINT
    { },
    // DXGI_FORMAT_R8G8_SNORM
    { },
    // DXGI_FORMAT_R8G8_SINT
    { },
    // DXGI_FORMAT_R16_TYPELESS
    { VK_FORMAT_R16_UNORM,
      VK_FORMAT_R16_SNORM,
      VK_FORMAT_R16_UINT,
      VK_FORMAT_R16_SINT,
      VK_FORMAT_R16_SFLOAT },
    // DXGI_FORMAT_R16_FLOAT
    { },
    // DXGI_FORMAT_D16_UNORM
    { },
    // DXGI_FORMAT_R16_UNORM
    { },
    // DXGI_FORMAT_R16_UINT
    { },
    // DXGI_FORMAT_R16_SNORM
    { },
    // DXGI_FORMAT_R16_SINT
    { },
    // DXGI_FORMAT_R8_TYPELESS
    { VK_FORMAT_R8_UNORM,
      VK_FORMAT_R8_SNORM,
      VK_FORMAT_R8_UINT,
      VK_FORMAT_R8_SINT },
    // DXGI_FORMAT_R8_UNORM
    { },
    // DXGI_FORMAT_R8_UINT
    { },
    // DXGI_FORMAT_R8_SNORM
    { },
    // DXGI_FORMAT_R8_SINT
    { },
    // DXGI_FORMAT_A8_UNORM
    { },
    // DXGI_FORMAT_R1_UNORM
    { }, // Unsupported
    // DXGI_FORMAT_R9G9B9E5_SHAREDEXP
    { },
    // DXGI_FORMAT_R8G8_B8G8_UNORM
    { },
    // DXGI_FORMAT_G8R8_G8B8_UNORM
    { },
    // DXGI_FORMAT_BC1_TYPELESS
    { VK_FORMAT_BC1_RGBA_UNORM_BLOCK,
      VK_FORMAT_BC1_RGBA_SRGB_BLOCK },
    // DXGI_FORMAT_BC1_UNORM
    { VK_FORMAT_BC1_RGBA_UNORM_BLOCK,
      VK_FORMAT_BC1_RGBA_SRGB_BLOCK },
    // DXGI_FORMAT_BC1_UNORM_SRGB
    { VK_FORMAT_BC1_RGBA_UNORM_BLOCK,
      VK_FORMAT_BC1_RGBA_SRGB_BLOCK },
    // DXGI_FORMAT_BC2_TYPELESS
    { VK_FORMAT_BC2_UNORM_BLOCK,
      VK_FORMAT_BC2_SRGB_BLOCK },
    // DXGI_FORMAT_BC2_UNORM
    { VK_FORMAT_BC2_UNORM_BLOCK,
      VK_FORMAT_BC2_SRGB_BLOCK },
    // DXGI_FORMAT_BC2_UNORM_SRGB
    { VK_FORMAT_BC2_UNORM_BLOCK,
      VK_FORMAT_BC2_SRGB_BLOCK },
    // DXGI_FORMAT_BC3_TYPELESS
    { VK_FORMAT_BC3_UNORM_BLOCK,
      VK_FORMAT_BC3_SRGB_BLOCK },
    // DXGI_FORMAT_BC3_UNORM
    { VK_FORMAT_BC3_UNORM_BLOCK,
      VK_FORMAT_BC3_SRGB_BLOCK },
    // DXGI_FORMAT_BC3_UNORM_SRGB
    { VK_FORMAT_BC3_UNORM_BLOCK,
      VK_FORMAT_BC3_SRGB_BLOCK },
    // DXGI_FORMAT_BC4_TYPELESS
    { VK_FORMAT_BC4_UNORM_BLOCK,
      VK_FORMAT_BC4_SNORM_BLOCK },
    // DXGI_FORMAT_BC4_UNORM
    { },
    // DXGI_FORMAT_BC4_SNORM
    { },
    // DXGI_FORMAT_BC5_TYPELESS
    { VK_FORMAT_BC5_UNORM_BLOCK,
      VK_FORMAT_BC5_SNORM_BLOCK },
    // DXGI_FORMAT_BC5_UNORM
    { },
    // DXGI_FORMAT_BC5_SNORM
    { },
    // DXGI_FORMAT_B5G6R5_UNORM
    { },
    // DXGI_FORMAT_B5G5R5A1_UNORM
    { },
    // DXGI_FORMAT_B8G8R8A8_UNORM
    { VK_FORMAT_B8G8R8A8_UNORM,
      VK_FORMAT_B8G8R8A8_SRGB },
    // DXGI_FORMAT_B8G8R8X8_UNORM
    { VK_FORMAT_B8G8R8A8_UNORM,
      VK_FORMAT_B8G8R8A8_SRGB },
    // DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM
    { }, // Unsupported
    // DXGI_FORMAT_B8G8R8A8_TYPELESS
    { VK_FORMAT_B8G8R8A8_UNORM,
      VK_FORMAT_B8G8R8A8_SRGB },
    // DXGI_FORMAT_B8G8R8A8_UNORM_SRGB
    { VK_FORMAT_B8G8R8A8_UNORM,
      VK_FORMAT_B8G8R8A8_SRGB },
    // DXGI_FORMAT_B8G8R8X8_TYPELESS
    { VK_FORMAT_B8G8R8A8_UNORM,
      VK_FORMAT_B8G8R8A8_SRGB },
    // DXGI_FORMAT_B8G8R8X8_UNORM_SRGB
    { VK_FORMAT_B8G8R8A8_UNORM,
      VK_FORMAT_B8G8R8A8_SRGB },
    // DXGI_FORMAT_BC6H_TYPELESS
    { VK_FORMAT_BC6H_UFLOAT_BLOCK,
      VK_FORMAT_BC6H_SFLOAT_BLOCK },
    // DXGI_FORMAT_BC6H_UF16
    { },
    // DXGI_FORMAT_BC6H_SF16
    { },
    // DXGI_FORMAT_BC7_TYPELESS
    { VK_FORMAT_BC7_UNORM_BLOCK,
      VK_FORMAT_BC7_SRGB_BLOCK },
    // DXGI_FORMAT_BC7_UNORM
    { VK_FORMAT_BC7_UNORM_BLOCK,
      VK_FORMAT_BC7_SRGB_BLOCK },
    // DXGI_FORMAT_BC7_UNORM_SRGB
    { VK_FORMAT_BC7_UNORM_BLOCK,
      VK_FORMAT_BC7_SRGB_BLOCK },
    // DXGI_FORMAT_AYUV
    { VK_FORMAT_R8G8B8A8_UNORM,
      VK_FORMAT_R8G8B8A8_UINT },
    // DXGI_FORMAT_Y410
    { }, // Unsupported
    // DXGI_FORMAT_Y416
    { }, // Unsupported
    // DXGI_FORMAT_NV12
    { VK_FORMAT_R8_UNORM,
      VK_FORMAT_R8G8_UNORM,
      VK_FORMAT_R8_UINT,
      VK_FORMAT_R8G8_UINT },
    // DXGI_FORMAT_P010
    { }, // Unsupported
    // DXGI_FORMAT_P016
    { }, // Unsupported
    // DXGI_FORMAT_420_OPAQUE
    { VK_FORMAT_R8_UNORM,
      VK_FORMAT_R8G8_UNORM,
      VK_FORMAT_R8_UINT,
      VK_FORMAT_R8G8_UINT },
    // DXGI_FORMAT_YUY2
    { VK_FORMAT_G8B8G8R8_422_UNORM,
      VK_FORMAT_R8G8B8A8_UNORM,
      VK_FORMAT_R8G8B8A8_UINT },
    // DXGI_FORMAT_Y210
    { }, // Unsupported
    // DXGI_FORMAT_Y216
    { }, // Unsupported
    // DXGI_FORMAT_NV11
    { }, // Unsupported
    // DXGI_FORMAT_AI44
    { }, // Unsupported
    // DXGI_FORMAT_IA44
    { }, // Unsupported
    // DXGI_FORMAT_P8
    { }, // Unsupported
    // DXGI_FORMAT_A8P8
    { }, // Unsupported
    // DXGI_FORMAT_B4G4R4A4_UNORM
    { }, // Unsupported
    // DXGI_FORMAT_P208
    { }, // Unsupported
    // DXGI_FORMAT_V208
    { }, // Unsupported
    // DXGI_FORMAT_V408
    { }, // Unsupported
  }};

  DXGIVkFormatTable::DXGIVkFormatTable(const Rc<DxvkAdapter>& adapter)
  : m_dxgiFormats (g_dxgiFormats), m_dxgiFamilies(g_dxgiFamilies) {
    // AMD do not support 24-bit depth buffers on Vulkan,
    // so we have to fall back to a 32-bit depth format.
    if (!CheckImageFormatSupport(adapter, VK_FORMAT_D24_UNORM_S8_UINT,
          VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT |
          VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {
      Logger::info("DXGI: VK_FORMAT_D24_UNORM_S8_UINT -> VK_FORMAT_D32_SFLOAT_S8_UINT");
      RemapDepthFormat(DXGI_FORMAT_R24G8_TYPELESS,        VK_FORMAT_D32_SFLOAT_S8_UINT);
      RemapDepthFormat(DXGI_FORMAT_R24_UNORM_X8_TYPELESS, VK_FORMAT_D32_SFLOAT_S8_UINT);
      RemapDepthFormat(DXGI_FORMAT_X24_TYPELESS_G8_UINT,  VK_FORMAT_D32_SFLOAT_S8_UINT);
      RemapDepthFormat(DXGI_FORMAT_D24_UNORM_S8_UINT,     VK_FORMAT_D32_SFLOAT_S8_UINT);
    }

    if (!adapter->features().ext4444Formats.formatA4R4G4B4) {
      RemapColorFormat(DXGI_FORMAT_B4G4R4A4_UNORM, VK_FORMAT_B4G4R4A4_UNORM_PACK16,
        { VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_R,
          VK_COMPONENT_SWIZZLE_A, VK_COMPONENT_SWIZZLE_B });
    }
  }

  DXGIVkFormatTable::~DXGIVkFormatTable() {

  }

  DXGI_VK_FORMAT_INFO DXGIVkFormatTable::GetFormatInfo(
          DXGI_FORMAT         Format,
          DXGI_VK_FORMAT_MODE Mode) const {
    return GetFormatInfoFromMapping(
      GetFormatMapping(Format), Mode);
  }

  DXGI_VK_FORMAT_INFO DXGIVkFormatTable::GetPackedFormatInfo(
          DXGI_FORMAT         Format,
          DXGI_VK_FORMAT_MODE Mode) const {
    return GetFormatInfoFromMapping(
      GetPackedFormatMapping(Format), Mode);
  }

  DXGI_VK_FORMAT_FAMILY DXGIVkFormatTable::GetFormatFamily(
          DXGI_FORMAT         Format,
          DXGI_VK_FORMAT_MODE Mode) const {
    if (Mode == DXGI_VK_FORMAT_MODE_DEPTH)
      return DXGI_VK_FORMAT_FAMILY();

    const size_t formatId = size_t(Format);

    return formatId < m_dxgiFamilies.size()
      ? m_dxgiFamilies[formatId]
      : m_dxgiFamilies[0];
  }

  DXGI_VK_FORMAT_INFO DXGIVkFormatTable::GetFormatInfoFromMapping(
    const DXGI_VK_FORMAT_MAPPING* pMapping,
          DXGI_VK_FORMAT_MODE   Mode) const {
    switch (Mode) {
      case DXGI_VK_FORMAT_MODE_ANY:
        return pMapping->FormatColor != VK_FORMAT_UNDEFINED
          ? DXGI_VK_FORMAT_INFO { pMapping->FormatColor, pMapping->AspectColor, pMapping->Swizzle }
          : DXGI_VK_FORMAT_INFO { pMapping->FormatDepth, pMapping->AspectDepth };

      case DXGI_VK_FORMAT_MODE_COLOR:
        return { pMapping->FormatColor, pMapping->AspectColor, pMapping->Swizzle };

      case DXGI_VK_FORMAT_MODE_DEPTH:
        return { pMapping->FormatDepth, pMapping->AspectDepth };

      case DXGI_VK_FORMAT_MODE_RAW:
        return { pMapping->FormatRaw, pMapping->AspectColor };
    }

    Logger::err("DXGI: GetFormatInfoFromMapping: Internal error");
    return DXGI_VK_FORMAT_INFO();
  }

  const DXGI_VK_FORMAT_MAPPING* DXGIVkFormatTable::GetFormatMapping(
          DXGI_FORMAT         Format) const {
    const size_t formatId = size_t(Format);

    return formatId < m_dxgiFormats.size()
      ? &m_dxgiFormats[formatId]
      : &m_dxgiFormats[0];
  }

  const DXGI_VK_FORMAT_MAPPING* DXGIVkFormatTable::GetPackedFormatMapping(
          DXGI_FORMAT         Format) const {
    const size_t formatId = size_t(Format);

    return formatId < g_dxgiFormats.size()
      ? &g_dxgiFormats[formatId]
      : &g_dxgiFormats[0];
  }

  bool DXGIVkFormatTable::CheckImageFormatSupport(
    const Rc<DxvkAdapter>&      Adapter,
          VkFormat              Format,
          VkFormatFeatureFlags  Features) const {
    VkFormatProperties supported = Adapter->formatProperties(Format);

    return (supported.linearTilingFeatures  & Features) == Features
        || (supported.optimalTilingFeatures & Features) == Features;
  }

  void DXGIVkFormatTable::RemapDepthFormat(
          DXGI_FORMAT         Format,
          VkFormat            Target) {
    m_dxgiFormats[uint32_t(Format)].FormatDepth = Target;
  }

  void DXGIVkFormatTable::RemapColorFormat(
          DXGI_FORMAT         Format,
          VkFormat            Target,
          VkComponentMapping  Swizzle) {
    m_dxgiFormats[uint32_t(Format)].FormatColor = Target;
    m_dxgiFormats[uint32_t(Format)].Swizzle = Swizzle;
  }

}


code:
#pragma once

#include "dxgi_include.h"

#include "../dxvk/dxvk_adapter.h"
#include "../dxvk/dxvk_format.h"

namespace dxvk {

  /**
   * \brief Format mapping
   *
   * Maps a DXGI format to a set of Vulkan formats.
   */
  struct DXGI_VK_FORMAT_MAPPING {
    VkFormat              FormatColor   = VK_FORMAT_UNDEFINED;  ///< Corresponding color format
    VkFormat              FormatDepth   = VK_FORMAT_UNDEFINED;  ///< Corresponding depth format
    VkFormat              FormatRaw     = VK_FORMAT_UNDEFINED;  ///< Bit-compatible integer format
    VkImageAspectFlags    AspectColor   = 0;                    ///< Defined aspects for the color format
    VkImageAspectFlags    AspectDepth   = 0;                    ///< Defined aspects for the depth format
    VkComponentMapping    Swizzle       = {                     ///< Color component swizzle
      VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
      VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY };
  };

  /**
   * \brief Format info
   *
   * Stores a Vulkan image format for a given
   * DXGI format and some additional information
   * on how resources with the particular format
   * are supposed to be used.
   */
  struct DXGI_VK_FORMAT_INFO {
    VkFormat              Format      = VK_FORMAT_UNDEFINED;  ///< Corresponding color format
    VkImageAspectFlags    Aspect      = 0;                    ///< Defined image aspect mask
    VkComponentMapping    Swizzle     = {                     ///< Component swizzle
      VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
      VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY };
  };

  /**
   * \brief Format lookup mode
   *
   * When looking up an image format, additional information
   * might be needed on how the image is going to be used.
   * This is used to properly map typeless formats and color
   * formats to depth formats if they are used on depth images.
   */
  enum DXGI_VK_FORMAT_MODE {
    DXGI_VK_FORMAT_MODE_ANY   = 0,  ///< Color first, then depth
    DXGI_VK_FORMAT_MODE_COLOR = 1,  ///< Color only
    DXGI_VK_FORMAT_MODE_DEPTH = 2,  ///< Depth only
    DXGI_VK_FORMAT_MODE_RAW   = 3,  ///< Unsigned integer format
  };

  /**
   * \brief Format family
   *
   * Stores a set of compatible formats. This can
   * be used to aggregate formats for the image
   * format list extension.
   */
  struct DXGI_VK_FORMAT_FAMILY {
    constexpr static size_t MaxSize = 8;

    DXGI_VK_FORMAT_FAMILY() { }
    DXGI_VK_FORMAT_FAMILY(const std::initializer_list<VkFormat>& FormatList) {
      for (VkFormat f : FormatList)
        Add(f);
    }

    BOOL Add(VkFormat Format) {
      for (UINT i = 0; i < FormatCount; i++) {
        if (Formats[i] == Format)
          return TRUE;
      }

      if (FormatCount < MaxSize) {
        Formats[FormatCount++] = Format;
        return TRUE;
      } return FALSE;
    }

    UINT     FormatCount = 0;
    VkFormat Formats[MaxSize];
  };

  /**
   * \brief Format table
   *
   * Initializes a format table for a specific
   * device and provides methods to look up
   * formats.
   */
  class DXGIVkFormatTable {

  public:

    DXGIVkFormatTable(
      const Rc<DxvkAdapter>& adapter);
    ~DXGIVkFormatTable();

    /**
     * \brief Retrieves info for a given DXGI format
     *
     * \param [in] Format The DXGI format to look up
     * \param [in] Mode the format lookup mode
     * \returns Format info
     */
    DXGI_VK_FORMAT_INFO GetFormatInfo(
            DXGI_FORMAT         Format,
            DXGI_VK_FORMAT_MODE Mode) const;

    /**
     * \brief Retrieves original info for a given DXGI format
     *
     * Doesn't perform any format adjustment, so this
     * can be used to determine the packed data format
     * of a DXGI format for things like data uploads.
     * \param [in] Format The DXGI format to look up
     * \param [in] Mode the format lookup mode
     * \returns Format info
     */
    DXGI_VK_FORMAT_INFO GetPackedFormatInfo(
            DXGI_FORMAT         Format,
            DXGI_VK_FORMAT_MODE Mode) const;

    /**
     * \brief Retrieves a format family
     *
     * \param [in] Format The format to query
     * \param [in] Mode Image format mode
     * \returns Image format family
     */
    DXGI_VK_FORMAT_FAMILY GetFormatFamily(
            DXGI_FORMAT         Format,
            DXGI_VK_FORMAT_MODE Mode) const;

  private:

    std::array<DXGI_VK_FORMAT_MAPPING, 133> m_dxgiFormats;
    std::array<DXGI_VK_FORMAT_FAMILY,  133> m_dxgiFamilies;

    DXGI_VK_FORMAT_INFO GetFormatInfoFromMapping(
      const DXGI_VK_FORMAT_MAPPING* pMapping,
            DXGI_VK_FORMAT_MODE   Mode) const;

    const DXGI_VK_FORMAT_MAPPING* GetFormatMapping(
            DXGI_FORMAT           Format) const;

    const DXGI_VK_FORMAT_MAPPING* GetPackedFormatMapping(
            DXGI_FORMAT           Format) const;

    bool CheckImageFormatSupport(
      const Rc<DxvkAdapter>&      Adapter,
            VkFormat              Format,
            VkFormatFeatureFlags  Features) const;

    void RemapDepthFormat(
            DXGI_FORMAT           Format,
            VkFormat              Target);

    void RemapColorFormat(
            DXGI_FORMAT           Format,
            VkFormat              Target,
            VkComponentMapping    Swizzle);

  };

};


code:
#pragma once

//for some reason we need to specify __declspec(dllexport) for MinGW
#if defined(__WINE__)
  #define DLLEXPORT __attribute__((visibility("default")))
#elif defined(_MSC_VER)
  #define DLLEXPORT
#else
  #define DLLEXPORT __declspec(dllexport)
#endif

#include "../util/com/com_guid.h"
#include "../util/com/com_object.h"
#include "../util/com/com_pointer.h"

#include "../util/log/log.h"
#include "../util/log/log_debug.h"

#include "../util/rc/util_rc.h"
#include "../util/rc/util_rc_ptr.h"

#include "../util/util_env.h"
#include "../util/util_enum.h"
#include "../util/util_error.h"
#include "../util/util_flags.h"
#include "../util/util_likely.h"
#include "../util/util_math.h"
#include "../util/util_monitor.h"
#include "../util/util_string.h"

#include <dxgi1_6.h>

// For some reason, these are not exposed
#ifndef DXGI_RESOURCE_PRIORITY_NORMAL
  #define DXGI_RESOURCE_PRIORITY_MINIMUM (0x28000000)
  #define DXGI_RESOURCE_PRIORITY_LOW (0x50000000)
  #define DXGI_RESOURCE_PRIORITY_NORMAL (0x78000000)
  #define DXGI_RESOURCE_PRIORITY_HIGH (0xa0000000)
  #define DXGI_RESOURCE_PRIORITY_MAXIMUM (0xc8000000)
#endif

#ifndef DXGI_CPU_ACCESS_NONE
  #define DXGI_CPU_ACCESS_NONE       (0)
  #define DXGI_CPU_ACCESS_DYNAMIC    (1)
  #define DXGI_CPU_ACCESS_READ_WRITE (2)
  #define DXGI_CPU_ACCESS_SCRATCH    (3)
  #define DXGI_CPU_ACCESS_FIELD      (0xf)
#endif