code:
#ifndef VULKAN_WIN32_H_
#define VULKAN_WIN32_H_ 1

/*
** Copyright 2015-2021 The Khronos Group Inc.
**
** SPDX-License-Identifier: Apache-2.0
*/

/*
** This header is generated from the Khronos Vulkan XML API Registry.
**
*/

#ifdef __cplusplus
extern "C" {
#endif

#define VK_KHR_win32_surface 1
#define VK_KHR_WIN32_SURFACE_SPEC_VERSION 6
#define VK_KHR_WIN32_SURFACE_EXTENSION_NAME "VK_KHR_win32_surface"
typedef VkFlags VkWin32SurfaceCreateFlagsKHR;
typedef struct VkWin32SurfaceCreateInfoKHR {
    VkStructureType                 sType;
    const void*                     pNext;
    VkWin32SurfaceCreateFlagsKHR    flags;
    HINSTANCE                       hinstance;
    HWND                            hwnd;
} VkWin32SurfaceCreateInfoKHR;

typedef VkResult (VKAPI_PTR *PFN_vkCreateWin32SurfaceKHR)(VkInstance instance, const VkWin32SurfaceCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);
typedef VkBool32 (VKAPI_PTR *PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR)(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex);

#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkCreateWin32SurfaceKHR(
    VkInstance                                  instance,
    const VkWin32SurfaceCreateInfoKHR*          pCreateInfo,
    const VkAllocationCallbacks*                pAllocator,
    VkSurfaceKHR*                               pSurface);

VKAPI_ATTR VkBool32 VKAPI_CALL vkGetPhysicalDeviceWin32PresentationSupportKHR(
    VkPhysicalDevice                            physicalDevice,
    uint32_t                                    queueFamilyIndex);
#endif

#define VK_KHR_external_memory_win32 1
#define VK_KHR_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1
#define VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_KHR_external_memory_win32"
typedef struct VkImportMemoryWin32HandleInfoKHR {
    VkStructureType                       sType;
    const void*                           pNext;
    VkExternalMemoryHandleTypeFlagBits    handleType;
    HANDLE                                handle;
    LPCWSTR                               name;
} VkImportMemoryWin32HandleInfoKHR;

typedef struct VkExportMemoryWin32HandleInfoKHR {
    VkStructureType               sType;
    const void*                   pNext;
    const SECURITY_ATTRIBUTES*    pAttributes;
    DWORD                         dwAccess;
    LPCWSTR                       name;
} VkExportMemoryWin32HandleInfoKHR;

typedef struct VkMemoryWin32HandlePropertiesKHR {
    VkStructureType    sType;
    void*              pNext;
    uint32_t           memoryTypeBits;
} VkMemoryWin32HandlePropertiesKHR;

typedef struct VkMemoryGetWin32HandleInfoKHR {
    VkStructureType                       sType;
    const void*                           pNext;
    VkDeviceMemory                        memory;
    VkExternalMemoryHandleTypeFlagBits    handleType;
} VkMemoryGetWin32HandleInfoKHR;

typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandleKHR)(VkDevice device, const VkMemoryGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle);
typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandlePropertiesKHR)(VkDevice device, VkExternalMemoryHandleTypeFlagBits handleType, HANDLE handle, VkMemoryWin32HandlePropertiesKHR* pMemoryWin32HandleProperties);

#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleKHR(
    VkDevice                                    device,
    const VkMemoryGetWin32HandleInfoKHR*        pGetWin32HandleInfo,
    HANDLE*                                     pHandle);

VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandlePropertiesKHR(
    VkDevice                                    device,
    VkExternalMemoryHandleTypeFlagBits          handleType,
    HANDLE                                      handle,
    VkMemoryWin32HandlePropertiesKHR*           pMemoryWin32HandleProperties);
#endif

#define VK_KHR_win32_keyed_mutex 1
#define VK_KHR_WIN32_KEYED_MUTEX_SPEC_VERSION 1
#define VK_KHR_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_KHR_win32_keyed_mutex"
typedef struct VkWin32KeyedMutexAcquireReleaseInfoKHR {
    VkStructureType          sType;
    const void*              pNext;
    uint32_t                 acquireCount;
    const VkDeviceMemory*    pAcquireSyncs;
    const uint64_t*          pAcquireKeys;
    const uint32_t*          pAcquireTimeouts;
    uint32_t                 releaseCount;
    const VkDeviceMemory*    pReleaseSyncs;
    const uint64_t*          pReleaseKeys;
} VkWin32KeyedMutexAcquireReleaseInfoKHR;

#define VK_KHR_external_semaphore_win32 1
#define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_SPEC_VERSION 1
#define VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME "VK_KHR_external_semaphore_win32"
typedef struct VkImportSemaphoreWin32HandleInfoKHR {
    VkStructureType                          sType;
    const void*                              pNext;
    VkSemaphore                              semaphore;
    VkSemaphoreImportFlags                   flags;
    VkExternalSemaphoreHandleTypeFlagBits    handleType;
    HANDLE                                   handle;
    LPCWSTR                                  name;
} VkImportSemaphoreWin32HandleInfoKHR;

typedef struct VkExportSemaphoreWin32HandleInfoKHR {
    VkStructureType               sType;
    const void*                   pNext;
    const SECURITY_ATTRIBUTES*    pAttributes;
    DWORD                         dwAccess;
    LPCWSTR                       name;
} VkExportSemaphoreWin32HandleInfoKHR;

typedef struct VkD3D12FenceSubmitInfoKHR {
    VkStructureType    sType;
    const void*        pNext;
    uint32_t           waitSemaphoreValuesCount;
    const uint64_t*    pWaitSemaphoreValues;
    uint32_t           signalSemaphoreValuesCount;
    const uint64_t*    pSignalSemaphoreValues;
} VkD3D12FenceSubmitInfoKHR;

typedef struct VkSemaphoreGetWin32HandleInfoKHR {
    VkStructureType                          sType;
    const void*                              pNext;
    VkSemaphore                              semaphore;
    VkExternalSemaphoreHandleTypeFlagBits    handleType;
} VkSemaphoreGetWin32HandleInfoKHR;

typedef VkResult (VKAPI_PTR *PFN_vkImportSemaphoreWin32HandleKHR)(VkDevice device, const VkImportSemaphoreWin32HandleInfoKHR* pImportSemaphoreWin32HandleInfo);
typedef VkResult (VKAPI_PTR *PFN_vkGetSemaphoreWin32HandleKHR)(VkDevice device, const VkSemaphoreGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle);

#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkImportSemaphoreWin32HandleKHR(
    VkDevice                                    device,
    const VkImportSemaphoreWin32HandleInfoKHR*  pImportSemaphoreWin32HandleInfo);

VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreWin32HandleKHR(
    VkDevice                                    device,
    const VkSemaphoreGetWin32HandleInfoKHR*     pGetWin32HandleInfo,
    HANDLE*                                     pHandle);
#endif

#define VK_KHR_external_fence_win32 1
#define VK_KHR_EXTERNAL_FENCE_WIN32_SPEC_VERSION 1
#define VK_KHR_EXTERNAL_FENCE_WIN32_EXTENSION_NAME "VK_KHR_external_fence_win32"
typedef struct VkImportFenceWin32HandleInfoKHR {
    VkStructureType                      sType;
    const void*                          pNext;
    VkFence                              fence;
    VkFenceImportFlags                   flags;
    VkExternalFenceHandleTypeFlagBits    handleType;
    HANDLE                               handle;
    LPCWSTR                              name;
} VkImportFenceWin32HandleInfoKHR;

typedef struct VkExportFenceWin32HandleInfoKHR {
    VkStructureType               sType;
    const void*                   pNext;
    const SECURITY_ATTRIBUTES*    pAttributes;
    DWORD                         dwAccess;
    LPCWSTR                       name;
} VkExportFenceWin32HandleInfoKHR;

typedef struct VkFenceGetWin32HandleInfoKHR {
    VkStructureType                      sType;
    const void*                          pNext;
    VkFence                              fence;
    VkExternalFenceHandleTypeFlagBits    handleType;
} VkFenceGetWin32HandleInfoKHR;

typedef VkResult (VKAPI_PTR *PFN_vkImportFenceWin32HandleKHR)(VkDevice device, const VkImportFenceWin32HandleInfoKHR* pImportFenceWin32HandleInfo);
typedef VkResult (VKAPI_PTR *PFN_vkGetFenceWin32HandleKHR)(VkDevice device, const VkFenceGetWin32HandleInfoKHR* pGetWin32HandleInfo, HANDLE* pHandle);

#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkImportFenceWin32HandleKHR(
    VkDevice                                    device,
    const VkImportFenceWin32HandleInfoKHR*      pImportFenceWin32HandleInfo);

VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceWin32HandleKHR(
    VkDevice                                    device,
    const VkFenceGetWin32HandleInfoKHR*         pGetWin32HandleInfo,
    HANDLE*                                     pHandle);
#endif

#define VK_NV_external_memory_win32 1
#define VK_NV_EXTERNAL_MEMORY_WIN32_SPEC_VERSION 1
#define VK_NV_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME "VK_NV_external_memory_win32"
typedef struct VkImportMemoryWin32HandleInfoNV {
    VkStructureType                      sType;
    const void*                          pNext;
    VkExternalMemoryHandleTypeFlagsNV    handleType;
    HANDLE                               handle;
} VkImportMemoryWin32HandleInfoNV;

typedef struct VkExportMemoryWin32HandleInfoNV {
    VkStructureType               sType;
    const void*                   pNext;
    const SECURITY_ATTRIBUTES*    pAttributes;
    DWORD                         dwAccess;
} VkExportMemoryWin32HandleInfoNV;

typedef VkResult (VKAPI_PTR *PFN_vkGetMemoryWin32HandleNV)(VkDevice device, VkDeviceMemory memory, VkExternalMemoryHandleTypeFlagsNV handleType, HANDLE* pHandle);

#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryWin32HandleNV(
    VkDevice                                    device,
    VkDeviceMemory                              memory,
    VkExternalMemoryHandleTypeFlagsNV           handleType,
    HANDLE*                                     pHandle);
#endif

#define VK_NV_win32_keyed_mutex 1
#define VK_NV_WIN32_KEYED_MUTEX_SPEC_VERSION 2
#define VK_NV_WIN32_KEYED_MUTEX_EXTENSION_NAME "VK_NV_win32_keyed_mutex"
typedef struct VkWin32KeyedMutexAcquireReleaseInfoNV {
    VkStructureType          sType;
    const void*              pNext;
    uint32_t                 acquireCount;
    const VkDeviceMemory*    pAcquireSyncs;
    const uint64_t*          pAcquireKeys;
    const uint32_t*          pAcquireTimeoutMilliseconds;
    uint32_t                 releaseCount;
    const VkDeviceMemory*    pReleaseSyncs;
    const uint64_t*          pReleaseKeys;
} VkWin32KeyedMutexAcquireReleaseInfoNV;

#define VK_EXT_full_screen_exclusive 1
#define VK_EXT_FULL_SCREEN_EXCLUSIVE_SPEC_VERSION 4
#define VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME "VK_EXT_full_screen_exclusive"

typedef enum VkFullScreenExclusiveEXT {
    VK_FULL_SCREEN_EXCLUSIVE_DEFAULT_EXT = 0,
    VK_FULL_SCREEN_EXCLUSIVE_ALLOWED_EXT = 1,
    VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT = 2,
    VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT = 3,
    VK_FULL_SCREEN_EXCLUSIVE_MAX_ENUM_EXT = 0x7FFFFFFF
} VkFullScreenExclusiveEXT;
typedef struct VkSurfaceFullScreenExclusiveInfoEXT {
    VkStructureType             sType;
    void*                       pNext;
    VkFullScreenExclusiveEXT    fullScreenExclusive;
} VkSurfaceFullScreenExclusiveInfoEXT;

typedef struct VkSurfaceCapabilitiesFullScreenExclusiveEXT {
    VkStructureType    sType;
    void*              pNext;
    VkBool32           fullScreenExclusiveSupported;
} VkSurfaceCapabilitiesFullScreenExclusiveEXT;

typedef struct VkSurfaceFullScreenExclusiveWin32InfoEXT {
    VkStructureType    sType;
    const void*        pNext;
    HMONITOR           hmonitor;
} VkSurfaceFullScreenExclusiveWin32InfoEXT;

typedef VkResult (VKAPI_PTR *PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT)(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, uint32_t* pPresentModeCount, VkPresentModeKHR* pPresentModes);
typedef VkResult (VKAPI_PTR *PFN_vkAcquireFullScreenExclusiveModeEXT)(VkDevice device, VkSwapchainKHR swapchain);
typedef VkResult (VKAPI_PTR *PFN_vkReleaseFullScreenExclusiveModeEXT)(VkDevice device, VkSwapchainKHR swapchain);
typedef VkResult (VKAPI_PTR *PFN_vkGetDeviceGroupSurfacePresentModes2EXT)(VkDevice device, const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo, VkDeviceGroupPresentModeFlagsKHR* pModes);

#ifndef VK_NO_PROTOTYPES
VKAPI_ATTR VkResult VKAPI_CALL vkGetPhysicalDeviceSurfacePresentModes2EXT(
    VkPhysicalDevice                            physicalDevice,
    const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
    uint32_t*                                   pPresentModeCount,
    VkPresentModeKHR*                           pPresentModes);

VKAPI_ATTR VkResult VKAPI_CALL vkAcquireFullScreenExclusiveModeEXT(
    VkDevice                                    device,
    VkSwapchainKHR                              swapchain);

VKAPI_ATTR VkResult VKAPI_CALL vkReleaseFullScreenExclusiveModeEXT(
    VkDevice                                    device,
    VkSwapchainKHR                              swapchain);

VKAPI_ATTR VkResult VKAPI_CALL vkGetDeviceGroupSurfacePresentModes2EXT(
    VkDevice                                    device,
    const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
    VkDeviceGroupPresentModeFlagsKHR*           pModes);
#endif

#ifdef __cplusplus
}
#endif

#endif

repo_name: orochi/dxvk


code:
; File generated automatically from d3dcompiler_43.spec; do not edit!

LIBRARY d3dcompiler_43.dll

EXPORTS
  D3DAssemble @1
  D3DCompile @3
  D3DCreateBlob @5
  D3DDisassemble @8
  D3DGetBlobPart @9
  D3DGetDebugInfo @10
  D3DGetInputAndOutputSignatureBlob @11
  D3DGetInputSignatureBlob @12
  D3DGetOutputSignatureBlob @13
  D3DPreprocess @14
  D3DReflect @15
  D3DStripShader @17


code:
; File generated automatically from d3dcompiler_43.spec; do not edit!

LIBRARY d3dcompiler_43.dll

EXPORTS
  D3DAssemble@32 @1
  D3DCompile@44 @3
  D3DCreateBlob@8 @5
  D3DDisassemble@20 @8
  D3DGetBlobPart@20 @9
  D3DGetDebugInfo@12 @10
  D3DGetInputAndOutputSignatureBlob@12 @11
  D3DGetInputSignatureBlob@12 @12
  D3DGetOutputSignatureBlob@12 @13
  D3DPreprocess@28 @14
  D3DReflect@16 @15
  D3DStripShader@16 @17


code:
project('dxvk', ['c', 'cpp'], version : 'v1.10.3', meson_version : '>= 0.49', default_options : [ 'cpp_std=c++17' ])

cpu_family = target_machine.cpu_family()

cpp = meson.get_compiler('cpp')
cc = meson.get_compiler('c')
dxvk_is_msvc = cpp.get_id() == 'msvc'

compiler_args = [
  '-DNOMINMAX',
  '-D_WIN32_WINNT=0xa00',
  '-msse',
  '-msse2',
  '-msse3',
  '-mfpmath=sse',
  '-Wimplicit-fallthrough',
  # clang
  '-Wno-unused-private-field',
  '-Wno-microsoft-exception-spec',
]

link_args = [
  '-static',
  '-static-libgcc',
  '-static-libstdc++',
  # We need to set the section alignment for debug symbols to
  # work properly as well as avoiding a memcpy from the Wine loader.
  '-Wl,--file-alignment=4096',
]

# Wine's built-in back traces only work with dwarf2 symbols
if get_option('debug') and target_machine.system() == 'windows'
  compiler_args += [
    '-gstrict-dwarf',
    '-gdwarf-2',
  ]
endif

if get_option('build_id')
  link_args += [
    '-Wl,--build-id',
  ]
endif

if cpu_family == 'x86'
  link_args += [
    '-Wl,--enable-stdcall-fixup',
    '-Wl,--add-stdcall-alias',
  ]
endif

add_project_arguments(cpp.get_supported_arguments(compiler_args), language: 'cpp')
add_project_arguments(cc.get_supported_arguments(compiler_args), language: 'c')
add_project_link_arguments(cpp.get_supported_link_arguments(link_args), language: 'cpp')
add_project_link_arguments(cc.get_supported_link_arguments(link_args), language: 'c')

dxvk_include_path = include_directories('./include')

if (cpu_family == 'x86_64')
  dxvk_library_path = meson.source_root() + '/lib'
else
  dxvk_library_path = meson.source_root() + '/lib32'
endif

dxvk_extradep = [ ]

lib_vulkan  = cpp.find_library('vulkan-1', dirs : dxvk_library_path)
lib_d3d9    = cpp.find_library('d3d9')
lib_d3d11   = cpp.find_library('d3d11')
lib_dxgi    = cpp.find_library('dxgi')
lib_d3dcompiler_43 = cpp.find_library('d3dcompiler_43', dirs : dxvk_library_path)

if dxvk_is_msvc
  lib_d3dcompiler_47 = cpp.find_library('d3dcompiler')
else
  lib_d3dcompiler_47 = cpp.find_library('d3dcompiler_47')
endif

exe_ext = ''
dll_ext = ''

def_spec_ext = '.def'

glsl_compiler = find_program('glslangValidator')
glsl_args = [ '-V', '--vn', '@BASENAME@', '@INPUT@', '-o', '@OUTPUT@' ]
if run_command(glsl_compiler, [ '--quiet', '--version' ], check : false).returncode() == 0
    glsl_args += [ '--quiet' ]
endif
glsl_generator = generator(glsl_compiler,
  output    : [ '@BASENAME@.h' ],
  arguments : glsl_args,
)

if dxvk_is_msvc
  res_ext = '.res'
  wrc = find_program('rc')
  wrc_generator = generator(wrc,
    output    : [ '@BASENAME@' + res_ext ],
    arguments : [ '/fo', '@OUTPUT@', '@INPUT@' ],
  )
else
  res_ext = '.o'
  wrc = find_program('windres')
  wrc_generator = generator(wrc,
    output    : [ '@BASENAME@' + res_ext ],
    arguments : [ '-i', '@INPUT@', '-o', '@OUTPUT@' ],
  )
endif

dxvk_version = vcs_tag(
  command: ['git', 'describe', '--dirty=+'],
  input:  'version.h.in',
  output: 'version.h',
)

subdir('src')

enable_tests = get_option('enable_tests')

if enable_tests
  subdir('tests')
endif


code:
option('enable_tests', type : 'boolean', value : false)
option('enable_dxgi',  type : 'boolean', value : true, description: 'Build DXGI')
option('enable_d3d9',  type : 'boolean', value : true, description: 'Build D3D9')
option('enable_d3d10', type : 'boolean', value : true, description: 'Build D3D10')
option('enable_d3d11', type : 'boolean', value : true, description: 'Build D3D11')
option('build_id',     type : 'boolean', value : false)


code:
#!/usr/bin/env bash

set -e

shopt -s extglob

if [ -z "$1" ] || [ -z "$2" ]; then
  echo "Usage: $0 version destdir [--no-package] [--dev-build]"
  exit 1
fi

DXVK_VERSION="$1"
DXVK_SRC_DIR=`dirname $(readlink -f $0)`
DXVK_BUILD_DIR=$(realpath "$2")"/dxvk-$DXVK_VERSION"
DXVK_ARCHIVE_PATH=$(realpath "$2")"/dxvk-$DXVK_VERSION.tar.gz"

if [ -e "$DXVK_BUILD_DIR" ]; then
  echo "Build directory $DXVK_BUILD_DIR already exists"
  exit 1
fi

shift 2

opt_nopackage=0
opt_devbuild=0
opt_buildid=false

crossfile="build-win"

while [ $# -gt 0 ]; do
  case "$1" in
  "--no-package")
    opt_nopackage=1
    ;;
  "--dev-build")
    opt_nopackage=1
    opt_devbuild=1
    ;;
  "--build-id")
    opt_buildid=true
    ;;
  *)
    echo "Unrecognized option: $1" >&2
    exit 1
  esac
  shift
done

function build_arch {
  export WINEARCH="win$1"
  export WINEPREFIX="$DXVK_BUILD_DIR/wine.$1"

  cd "$DXVK_SRC_DIR"

  opt_strip=
  if [ $opt_devbuild -eq 0 ]; then
    opt_strip=--strip
  fi

  meson --cross-file "$DXVK_SRC_DIR/$crossfile$1.txt" \
        --buildtype "release"                         \
        --prefix "$DXVK_BUILD_DIR"                    \
        $opt_strip                                    \
        --bindir "x$1"                                \
        --libdir "x$1"                                \
        -Denable_tests=false                          \
        -Dbuild_id=$opt_buildid                       \
        "$DXVK_BUILD_DIR/build.$1"

  cd "$DXVK_BUILD_DIR/build.$1"
  ninja install

  if [ $opt_devbuild -eq 0 ]; then
    # get rid of some useless .a files
    rm "$DXVK_BUILD_DIR/x$1/"*.!(dll)
    rm -R "$DXVK_BUILD_DIR/build.$1"
  fi
}

function build_script {
  cp "$DXVK_SRC_DIR/setup_dxvk.sh" "$DXVK_BUILD_DIR/setup_dxvk.sh"
  chmod +x "$DXVK_BUILD_DIR/setup_dxvk.sh"
}

function package {
  cd "$DXVK_BUILD_DIR/.."
  tar -czf "$DXVK_ARCHIVE_PATH" "dxvk-$DXVK_VERSION"
  rm -R "dxvk-$DXVK_VERSION"
}

build_arch 64
build_arch 32
build_script

if [ $opt_nopackage -eq 0 ]; then
  package
fi


code:
#!/usr/bin/env bash

# default directories
dxvk_lib32=${dxvk_lib32:-"x32"}
dxvk_lib64=${dxvk_lib64:-"x64"}

# figure out where we are
basedir=$(dirname "$(readlink -f $0)")

# figure out which action to perform
action="$1"

case "$action" in
install)
  ;;
uninstall)
  ;;
*)
  echo "Unrecognized action: $action"
  echo "Usage: $0 [install|uninstall] [--without-dxgi] [--with-d3d10] [--symlink]"
  exit 1
esac

# process arguments
shift

with_dxgi=true
with_d3d10=false
file_cmd="cp -v"

while (($# > 0)); do
  case "$1" in
  "--without-dxgi")
    with_dxgi=false
    ;;
  "--with-d3d10")
    with_d3d10=true
    ;;
  "--symlink")
    file_cmd="ln -s -v"
    ;;
  esac
  shift
done

# check wine prefix before invoking wine, so that we
# don't accidentally create one if the user screws up
if [ -n "$WINEPREFIX" ] && ! [ -f "$WINEPREFIX/system.reg" ]; then
  echo "$WINEPREFIX:"' Not a valid wine prefix.' >&2
  exit 1
fi

# find wine executable
export WINEDEBUG=-all
# disable mscoree and mshtml to avoid downloading
# wine gecko and mono
export WINEDLLOVERRIDES="mscoree,mshtml="

wine="wine"
wine64="wine64"
wineboot="wineboot"

# $PATH is the way for user to control where wine is located (including custom Wine versions).
# Pure 64-bit Wine (non Wow64) requries skipping 32-bit steps.
# In such case, wine64 and winebooot will be present, but wine binary will be missing,
# however it can be present in other PATHs, so it shouldn't be used, to avoid versions mixing.
wine_path=$(dirname "$(which $wineboot)")
wow64=true
if ! [ -f "$wine_path/$wine" ]; then
   wine=$wine64
   wow64=false
fi

# resolve 32-bit and 64-bit system32 path
winever=$($wine --version | grep wine)
if [ -z "$winever" ]; then
    echo "$wine:"' Not a wine executable. Check your $wine.' >&2
    exit 1
fi

# ensure wine placeholder dlls are recreated
# if they are missing
$wineboot -u

win64_sys_path=$($wine64 winepath -u 'C:\windows\system32' 2> /dev/null)
win64_sys_path="${win64_sys_path/$'\r'/}"
if $wow64; then
  win32_sys_path=$($wine winepath -u 'C:\windows\system32' 2> /dev/null)
  win32_sys_path="${win32_sys_path/$'\r'/}"
fi

if [ -z "$win32_sys_path" ] && [ -z "$win64_sys_path" ]; then
  echo 'Failed to resolve C:\windows\system32.' >&2
  exit 1
fi

# create native dll override
overrideDll() {
  $wine reg add 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v $1 /d native /f >/dev/null 2>&1
  if [ $? -ne 0 ]; then
    echo -e "Failed to add override for $1"
    exit 1
  fi
}

# remove dll override
restoreDll() {
  $wine reg delete 'HKEY_CURRENT_USER\Software\Wine\DllOverrides' /v $1 /f > /dev/null 2>&1
  if [ $? -ne 0 ]; then
    echo "Failed to remove override for $1"
  fi
}

# copy or link dxvk dll, back up original file
installFile() {
  dstfile="${1}/${3}.dll"
  srcfile="${basedir}/${2}/${3}.dll"

  if [ -f "${srcfile}.so" ]; then
    srcfile="${srcfile}.so"
  fi

  if ! [ -f "${srcfile}" ]; then
    echo "${srcfile}: File not found. Skipping." >&2
    return 1
  fi

  if [ -n "$1" ]; then
    if [ -f "${dstfile}" ] || [ -h "${dstfile}" ]; then
      if ! [ -f "${dstfile}.old" ]; then
        mv -v "${dstfile}" "${dstfile}.old"
      else
        rm -v "${dstfile}"
      fi
      $file_cmd "${srcfile}" "${dstfile}"
    else
      echo "${dstfile}: File not found in wine prefix" >&2
      return 1
    fi
  fi
  return 0
}

# remove dxvk dll, restore original file
uninstallFile() {
  dstfile="${1}/${3}.dll"
  srcfile="${basedir}/${2}/${3}.dll"

  if [ -f "${srcfile}.so" ]; then
    srcfile="${srcfile}.so"
  fi

  if ! [ -f "${srcfile}" ]; then
    echo "${srcfile}: File not found. Skipping." >&2
    return 1
  fi

  if ! [ -f "${dstfile}" ] && ! [ -h "${dstfile}" ]; then
    echo "${dstfile}: File not found. Skipping." >&2
    return 1
  fi

  if [ -f "${dstfile}.old" ]; then
    rm -v "${dstfile}"
    mv -v "${dstfile}.old" "${dstfile}"
    return 0
  else
    return 1
  fi
}

install() {
  installFile "$win64_sys_path" "$dxvk_lib64" "$1"
  inst64_ret="$?"

  inst32_ret=-1
  if $wow64; then
    installFile "$win32_sys_path" "$dxvk_lib32" "$1"
    inst32_ret="$?"
  fi

  if (( ($inst32_ret == 0) || ($inst64_ret == 0) )); then
    overrideDll "$1"
  fi
}

uninstall() {
  uninstallFile "$win64_sys_path" "$dxvk_lib64" "$1"
  uninst64_ret="$?"

  uninst32_ret=-1
  if $wow64; then
    uninstallFile "$win32_sys_path" "$dxvk_lib32" "$1"
    uninst32_ret="$?"
  fi

  if (( ($uninst32_ret == 0) || ($uninst64_ret == 0) )); then
    restoreDll "$1"
  fi
}

# skip dxgi during install if not explicitly
# enabled, but always try to uninstall it
if $with_dxgi || [ "$action" == "uninstall" ]; then
  $action dxgi
fi

$action d3d9

if $with_d3d10 || [ "$action" == "uninstall" ]; then
  $action d3d10
  $action d3d10_1
fi

$action d3d10core
$action d3d11


code:
LIBRARY D3D10.DLL
EXPORTS
    D3D10CreateDevice
    D3D10CreateDeviceAndSwapChain
    D3D10GetVertexShaderProfile
    D3D10GetGeometryShaderProfile
    D3D10GetPixelShaderProfile
    D3D10CreateBlob
    D3D10GetInputSignatureBlob
    D3D10GetOutputSignatureBlob
    D3D10ReflectShader
    D3D10CompileShader
    D3D10CreateEffectFromMemory
    D3D10CreateEffectPoolFromMemory
    D3D10CompileEffectFromMemory
    D3D10DisassembleEffect
    D3D10DisassembleShader
    D3D10PreprocessShader
    D3D10CreateStateBlock
    D3D10StateBlockMaskDifference
    D3D10StateBlockMaskDisableAll
    D3D10StateBlockMaskDisableCapture
    D3D10StateBlockMaskEnableAll
    D3D10StateBlockMaskEnableCapture
    D3D10StateBlockMaskGetSetting
    D3D10StateBlockMaskIntersect
    D3D10StateBlockMaskUnion
    D3D10GetVersion
    D3D10RegisterLayers


code:
LIBRARY D3D10_1.DLL
EXPORTS
    D3D10CreateDevice1
    D3D10CreateDeviceAndSwapChain1
    D3D10GetVertexShaderProfile
    D3D10GetGeometryShaderProfile
    D3D10GetPixelShaderProfile
    D3D10CreateBlob
    D3D10GetInputSignatureBlob
    D3D10GetOutputSignatureBlob
    D3D10ReflectShader
    D3D10CompileShader
    D3D10CreateEffectFromMemory
    D3D10CreateEffectPoolFromMemory
    D3D10CompileEffectFromMemory
    D3D10DisassembleEffect
    D3D10DisassembleShader
    D3D10PreprocessShader
    D3D10CreateStateBlock
    D3D10StateBlockMaskDifference
    D3D10StateBlockMaskDisableAll
    D3D10StateBlockMaskDisableCapture
    D3D10StateBlockMaskEnableAll
    D3D10StateBlockMaskEnableCapture
    D3D10StateBlockMaskGetSetting
    D3D10StateBlockMaskIntersect
    D3D10StateBlockMaskUnion
    D3D10GetVersion
    D3D10RegisterLayers


code:
#include "d3d10_blend.h"

#include "../d3d11/d3d11_blend.h"
#include "../d3d11/d3d11_device.h"

namespace dxvk {

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

  ULONG STDMETHODCALLTYPE D3D10BlendState::AddRef() {
    return m_d3d11->AddRef();
  }

  ULONG STDMETHODCALLTYPE D3D10BlendState::Release() {
    return m_d3d11->Release();
  }

  void STDMETHODCALLTYPE D3D10BlendState::GetDevice(
          ID3D10Device**            ppDevice) {
    GetD3D10Device(m_d3d11, ppDevice);
  }

  HRESULT STDMETHODCALLTYPE D3D10BlendState::GetPrivateData(
          REFGUID                   guid,
          UINT*                     pDataSize,
          void*                     pData) {
    return m_d3d11->GetPrivateData(guid, pDataSize, pData);
  }

  HRESULT STDMETHODCALLTYPE D3D10BlendState::SetPrivateData(
          REFGUID                   guid,
          UINT                      DataSize,
    const void*                     pData) {
    return m_d3d11->SetPrivateData(guid, DataSize, pData);
  }

  HRESULT STDMETHODCALLTYPE D3D10BlendState::SetPrivateDataInterface(
          REFGUID                   guid,
    const IUnknown*                 pData) {
    return m_d3d11->SetPrivateDataInterface(guid, pData);
  }

  void STDMETHODCALLTYPE D3D10BlendState::GetDesc(
          D3D10_BLEND_DESC*         pDesc) {
    D3D11_BLEND_DESC d3d11Desc;
    m_d3d11->GetDesc(&d3d11Desc);

    pDesc->AlphaToCoverageEnable  = d3d11Desc.AlphaToCoverageEnable;
    pDesc->SrcBlend               = D3D10_BLEND   (d3d11Desc.RenderTarget[0].SrcBlend);
    pDesc->DestBlend              = D3D10_BLEND   (d3d11Desc.RenderTarget[0].DestBlend);
    pDesc->BlendOp                = D3D10_BLEND_OP(d3d11Desc.RenderTarget[0].BlendOp);
    pDesc->SrcBlendAlpha          = D3D10_BLEND   (d3d11Desc.RenderTarget[0].SrcBlendAlpha);
    pDesc->DestBlendAlpha         = D3D10_BLEND   (d3d11Desc.RenderTarget[0].DestBlendAlpha);
    pDesc->BlendOpAlpha           = D3D10_BLEND_OP(d3d11Desc.RenderTarget[0].BlendOpAlpha);

    for (uint32_t i = 0; i < 8; i++) {
      uint32_t srcId = d3d11Desc.IndependentBlendEnable ? i : 0;
      pDesc->BlendEnable[i]           = d3d11Desc.RenderTarget[srcId].BlendEnable;
      pDesc->RenderTargetWriteMask[i] = d3d11Desc.RenderTarget[srcId].RenderTargetWriteMask;
    }
  }

  void STDMETHODCALLTYPE D3D10BlendState::GetDesc1(
          D3D10_BLEND_DESC1*        pDesc) {
    static_assert(sizeof(D3D10_BLEND_DESC1) == sizeof(D3D11_BLEND_DESC));
    m_d3d11->GetDesc(reinterpret_cast<D3D11_BLEND_DESC*>(pDesc));
  }

}


code:
#pragma once

#include "d3d10_util.h"

namespace dxvk {

  class D3D11BlendState;
  class D3D11Device;

  class D3D10BlendState : public ID3D10BlendState1 {

  public:

    D3D10BlendState(D3D11BlendState* pParent)
    : m_d3d11(pParent) { }

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

    ULONG STDMETHODCALLTYPE AddRef();

    ULONG STDMETHODCALLTYPE Release();

    void STDMETHODCALLTYPE GetDevice(
            ID3D10Device**            ppDevice);

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

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

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

    void STDMETHODCALLTYPE GetDesc(
            D3D10_BLEND_DESC*         pDesc);

    void STDMETHODCALLTYPE GetDesc1(
            D3D10_BLEND_DESC1*        pDesc);

    D3D11BlendState* GetD3D11Iface() {
      return m_d3d11;
    }

  private:

    D3D11BlendState* m_d3d11;

  };

}


code:
#include "d3d10_buffer.h"

#include "../d3d11/d3d11_buffer.h"
#include "../d3d11/d3d11_device.h"
#include "../d3d11/d3d11_context.h"

namespace dxvk {

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

  ULONG STDMETHODCALLTYPE D3D10Buffer::AddRef() {
    return m_d3d11->AddRef();
  }

  ULONG STDMETHODCALLTYPE D3D10Buffer::Release() {
    return m_d3d11->Release();
  }

  void STDMETHODCALLTYPE D3D10Buffer::GetDevice(
          ID3D10Device**            ppDevice) {
    GetD3D10Device(m_d3d11, ppDevice);
  }

  HRESULT STDMETHODCALLTYPE D3D10Buffer::GetPrivateData(
          REFGUID                   guid,
          UINT*                     pDataSize,
          void*                     pData) {
    return m_d3d11->GetPrivateData(guid, pDataSize, pData);
  }

  HRESULT STDMETHODCALLTYPE D3D10Buffer::SetPrivateData(
          REFGUID                   guid,
          UINT                      DataSize,
    const void*                     pData) {
    return m_d3d11->SetPrivateData(guid, DataSize, pData);
  }

  HRESULT STDMETHODCALLTYPE D3D10Buffer::SetPrivateDataInterface(
          REFGUID                   guid,
    const IUnknown*                 pData) {
    return m_d3d11->SetPrivateDataInterface(guid, pData);
  }

  void STDMETHODCALLTYPE D3D10Buffer::GetType(
          D3D10_RESOURCE_DIMENSION* rType) {
    *rType = D3D10_RESOURCE_DIMENSION_BUFFER;
  }

  void STDMETHODCALLTYPE D3D10Buffer::SetEvictionPriority(
          UINT                      EvictionPriority) {
    m_d3d11->SetEvictionPriority(EvictionPriority);
  }

  UINT STDMETHODCALLTYPE D3D10Buffer::GetEvictionPriority() {
    return m_d3d11->GetEvictionPriority();
  }

  HRESULT STDMETHODCALLTYPE D3D10Buffer::Map(
          D3D10_MAP                 MapType,
          UINT                      MapFlags,
          void**                    ppData) {
    Com<ID3D11DeviceContext> ctx;
    GetD3D11Context(m_d3d11, &ctx);

    D3D11_MAPPED_SUBRESOURCE sr;
    HRESULT hr = ctx->Map(m_d3d11, 0,
      D3D11_MAP(MapType), MapFlags, &sr);

    if (FAILED(hr))
      return hr;

    if (ppData != nullptr) {
      *ppData = sr.pData;
      return S_OK;
    } return S_FALSE;
  }

  void STDMETHODCALLTYPE D3D10Buffer::Unmap() {
    Com<ID3D11DeviceContext> ctx;
    GetD3D11Context(m_d3d11, &ctx);

    ctx->Unmap(m_d3d11, 0);
  }

  void STDMETHODCALLTYPE D3D10Buffer::GetDesc(
          D3D10_BUFFER_DESC*        pDesc) {
    D3D11_BUFFER_DESC d3d11Desc;
    m_d3d11->GetDesc(&d3d11Desc);

    pDesc->ByteWidth       = d3d11Desc.ByteWidth;
    pDesc->Usage           = D3D10_USAGE(d3d11Desc.Usage);
    pDesc->BindFlags       = d3d11Desc.BindFlags;
    pDesc->CPUAccessFlags  = d3d11Desc.CPUAccessFlags;
    pDesc->MiscFlags       = ConvertD3D11ResourceFlags(d3d11Desc.MiscFlags);
  }

}


code:
#pragma once

#include "d3d10_util.h"

namespace dxvk {

  class D3D11Buffer;
  class D3D11Device;
  class D3D10Device;

  class D3D10Buffer : public ID3D10Buffer {

  public:

    D3D10Buffer(D3D11Buffer* pParent)
    : m_d3d11(pParent) { }

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

    ULONG STDMETHODCALLTYPE AddRef();

    ULONG STDMETHODCALLTYPE Release();

    void STDMETHODCALLTYPE GetDevice(
            ID3D10Device**            ppDevice);

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

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

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

    void STDMETHODCALLTYPE GetType(
            D3D10_RESOURCE_DIMENSION* rType);

    void STDMETHODCALLTYPE SetEvictionPriority(
            UINT                      EvictionPriority);

    UINT STDMETHODCALLTYPE GetEvictionPriority();

    HRESULT STDMETHODCALLTYPE Map(
            D3D10_MAP                 MapType,
            UINT                      MapFlags,
            void**                    ppData);

    void STDMETHODCALLTYPE Unmap();

    void STDMETHODCALLTYPE GetDesc(
            D3D10_BUFFER_DESC*        pDesc);

    D3D11Buffer* GetD3D11Iface() {
      return m_d3d11;
    }

  private:

    D3D11Buffer* m_d3d11;

  };

}


code:
#include <d3d11.h>
#include <d3d10_1.h>

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

extern "C" {
  using namespace dxvk;

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

  DLLEXPORT HRESULT __stdcall D3D10CoreCreateDevice(
          IDXGIFactory*           pFactory,
          IDXGIAdapter*           pAdapter,
          UINT                    Flags,
          D3D_FEATURE_LEVEL       FeatureLevel,
          ID3D10Device**          ppDevice) {
    InitReturnPtr(ppDevice);

    Com<ID3D11Device> d3d11Device;

    HRESULT hr = pAdapter->CheckInterfaceSupport(
      __uuidof(ID3D10Device), nullptr);

    if (FAILED(hr))
      return hr;

    hr = D3D11CoreCreateDevice(pFactory, pAdapter,
      Flags, &FeatureLevel, 1, &d3d11Device);

    if (FAILED(hr))
      return hr;

    Com<ID3D10Multithread> multithread;
    d3d11Device->QueryInterface(__uuidof(ID3D10Multithread), reinterpret_cast<void**>(&multithread));
    multithread->SetMultithreadProtected(!(Flags & D3D10_CREATE_DEVICE_SINGLETHREADED));

    Com<IDXGIDXVKDevice> dxvkDevice;
    d3d11Device->QueryInterface(__uuidof(IDXGIDXVKDevice), reinterpret_cast<void**>(&dxvkDevice));
    dxvkDevice->SetAPIVersion(10);

    if (FAILED(d3d11Device->QueryInterface(
        __uuidof(ID3D10Device), reinterpret_cast<void**>(ppDevice))))
      return E_FAIL;

    return S_OK;
  }

  UINT64 STDMETHODCALLTYPE D3D10CoreGetVersion() {
    // Match the Windows 10 return value, but we
    // don't know the exact function signature
    return 0xa000100041770ull;
  }

  HRESULT STDMETHODCALLTYPE D3D10CoreRegisterLayers() {
    return E_NOTIMPL;
  }

}


code:
#include "d3d10_depth_stencil.h"

#include "../d3d11/d3d11_depth_stencil.h"
#include "../d3d11/d3d11_device.h"

namespace dxvk {

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

  ULONG STDMETHODCALLTYPE D3D10DepthStencilState::AddRef() {
    return m_d3d11->AddRef();
  }

  ULONG STDMETHODCALLTYPE D3D10DepthStencilState::Release() {
    return m_d3d11->Release();
  }

  void STDMETHODCALLTYPE D3D10DepthStencilState::GetDevice(
          ID3D10Device**            ppDevice) {
    GetD3D10Device(m_d3d11, ppDevice);
  }

  HRESULT STDMETHODCALLTYPE D3D10DepthStencilState::GetPrivateData(
          REFGUID                   guid,
          UINT*                     pDataSize,
          void*                     pData) {
    return m_d3d11->GetPrivateData(guid, pDataSize, pData);
  }

  HRESULT STDMETHODCALLTYPE D3D10DepthStencilState::SetPrivateData(
          REFGUID                   guid,
          UINT                      DataSize,
    const void*                     pData) {
    return m_d3d11->SetPrivateData(guid, DataSize, pData);
  }

  HRESULT STDMETHODCALLTYPE D3D10DepthStencilState::SetPrivateDataInterface(
          REFGUID                   guid,
    const IUnknown*                 pData) {
    return m_d3d11->SetPrivateDataInterface(guid, pData);
  }

  void STDMETHODCALLTYPE D3D10DepthStencilState::GetDesc(
          D3D10_DEPTH_STENCIL_DESC* pDesc) {
    static_assert(sizeof(D3D10_DEPTH_STENCIL_DESC) == sizeof(D3D11_DEPTH_STENCIL_DESC));
    m_d3d11->GetDesc(reinterpret_cast<D3D11_DEPTH_STENCIL_DESC*>(pDesc));
  }

}


code:
#pragma once

#include "d3d10_util.h"

namespace dxvk {

  class D3D11DepthStencilState;
  class D3D11Device;

  class D3D10DepthStencilState : public ID3D10DepthStencilState {

  public:

    D3D10DepthStencilState(D3D11DepthStencilState* pParent)
    : m_d3d11(pParent) { }

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

    ULONG STDMETHODCALLTYPE AddRef();

    ULONG STDMETHODCALLTYPE Release();

    void STDMETHODCALLTYPE GetDevice(
            ID3D10Device**            ppDevice);

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

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

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

    void STDMETHODCALLTYPE GetDesc(
            D3D10_DEPTH_STENCIL_DESC* pDesc);

    D3D11DepthStencilState* GetD3D11Iface() {
      return m_d3d11;
    }

  private:

    D3D11DepthStencilState* m_d3d11;

  };

}


code:
#include "d3d10_device.h"

#include "../d3d11/d3d11_device.h"
#include "../d3d11/d3d11_context_imm.h"

namespace dxvk {

  D3D10Device::D3D10Device(
          D3D11Device*                      pDevice,
          D3D11ImmediateContext*            pContext)
  : m_device(pDevice), m_context(pContext) {
  }

  D3D10Device::~D3D10Device() {

  }

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

  ULONG STDMETHODCALLTYPE D3D10Device::AddRef() {
    return m_device->AddRef();
  }

  ULONG STDMETHODCALLTYPE D3D10Device::Release() {
    return m_device->Release();
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::GetPrivateData(
          REFGUID                           guid,
          UINT*                             pDataSize,
          void*                             pData) {
    return m_device->GetPrivateData(guid, pDataSize, pData);
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::SetPrivateData(
          REFGUID                           guid,
          UINT                              DataSize,
    const void*                             pData) {
    return m_device->SetPrivateData(guid, DataSize, pData);
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::SetPrivateDataInterface(
          REFGUID                           guid,
    const IUnknown*                         pData) {
    return m_device->SetPrivateDataInterface(guid, pData);
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::GetDeviceRemovedReason() {
    return m_device->GetDeviceRemovedReason();
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::SetExceptionMode(
          UINT                              RaiseFlags) {
    return m_device->SetExceptionMode(RaiseFlags);
  }

  UINT STDMETHODCALLTYPE D3D10Device::GetExceptionMode() {
    return m_device->GetExceptionMode();
  }

  D3D10_FEATURE_LEVEL1 STDMETHODCALLTYPE D3D10Device::GetFeatureLevel() {
    return D3D10_FEATURE_LEVEL1(m_device->GetFeatureLevel());
  }

  void STDMETHODCALLTYPE D3D10Device::ClearState() {
    m_context->ClearState();
  }

  void STDMETHODCALLTYPE D3D10Device::Flush() {
    m_context->Flush();
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::CreateBuffer(
    const D3D10_BUFFER_DESC*                pDesc,
    const D3D10_SUBRESOURCE_DATA*           pInitialData,
          ID3D10Buffer**                    ppBuffer) {
    InitReturnPtr(ppBuffer);

    if (pDesc == nullptr)
      return E_INVALIDARG;

    D3D11_BUFFER_DESC d3d11Desc;
    d3d11Desc.ByteWidth       = pDesc->ByteWidth;
    d3d11Desc.Usage           = D3D11_USAGE(pDesc->Usage);
    d3d11Desc.BindFlags       = pDesc->BindFlags;
    d3d11Desc.CPUAccessFlags  = pDesc->CPUAccessFlags;
    d3d11Desc.MiscFlags       = ConvertD3D10ResourceFlags(pDesc->MiscFlags);
    d3d11Desc.StructureByteStride = 0;

    ID3D11Buffer* d3d11Buffer = nullptr;
    HRESULT hr = m_device->CreateBuffer(&d3d11Desc,
      reinterpret_cast<const D3D11_SUBRESOURCE_DATA*>(pInitialData),
      ppBuffer != nullptr ? &d3d11Buffer : nullptr);

    if (hr != S_OK)
      return hr;

    *ppBuffer = static_cast<D3D11Buffer*>(d3d11Buffer)->GetD3D10Iface();
    return S_OK;
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::CreateTexture1D(
    const D3D10_TEXTURE1D_DESC*             pDesc,
    const D3D10_SUBRESOURCE_DATA*           pInitialData,
          ID3D10Texture1D**                 ppTexture1D) {
    InitReturnPtr(ppTexture1D);

    if (pDesc == nullptr)
      return E_INVALIDARG;

    D3D11_TEXTURE1D_DESC d3d11Desc;
    d3d11Desc.Width           = pDesc->Width;
    d3d11Desc.MipLevels       = pDesc->MipLevels;
    d3d11Desc.ArraySize       = pDesc->ArraySize;
    d3d11Desc.Format          = pDesc->Format;
    d3d11Desc.Usage           = D3D11_USAGE(pDesc->Usage);
    d3d11Desc.BindFlags       = pDesc->BindFlags;
    d3d11Desc.CPUAccessFlags  = pDesc->CPUAccessFlags;
    d3d11Desc.MiscFlags       = ConvertD3D10ResourceFlags(pDesc->MiscFlags);

    ID3D11Texture1D* d3d11Texture1D = nullptr;
    HRESULT hr = m_device->CreateTexture1D(&d3d11Desc,
      reinterpret_cast<const D3D11_SUBRESOURCE_DATA*>(pInitialData),
      ppTexture1D != nullptr ? &d3d11Texture1D : nullptr);

    if (hr != S_OK)
      return hr;

    *ppTexture1D = static_cast<D3D11Texture1D*>(d3d11Texture1D)->GetD3D10Iface();
    return S_OK;
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::CreateTexture2D(
    const D3D10_TEXTURE2D_DESC*             pDesc,
    const D3D10_SUBRESOURCE_DATA*           pInitialData,
          ID3D10Texture2D**                 ppTexture2D) {
    InitReturnPtr(ppTexture2D);

    if (pDesc == nullptr)
      return E_INVALIDARG;

    D3D11_TEXTURE2D_DESC d3d11Desc;
    d3d11Desc.Width           = pDesc->Width;
    d3d11Desc.Height          = pDesc->Height;
    d3d11Desc.MipLevels       = pDesc->MipLevels;
    d3d11Desc.ArraySize       = pDesc->ArraySize;
    d3d11Desc.Format          = pDesc->Format;
    d3d11Desc.SampleDesc      = pDesc->SampleDesc;
    d3d11Desc.Usage           = D3D11_USAGE(pDesc->Usage);
    d3d11Desc.BindFlags       = pDesc->BindFlags;
    d3d11Desc.CPUAccessFlags  = pDesc->CPUAccessFlags;
    d3d11Desc.MiscFlags       = ConvertD3D10ResourceFlags(pDesc->MiscFlags);

    ID3D11Texture2D* d3d11Texture2D = nullptr;
    HRESULT hr = m_device->CreateTexture2D(&d3d11Desc,
      reinterpret_cast<const D3D11_SUBRESOURCE_DATA*>(pInitialData),
      ppTexture2D != nullptr ? &d3d11Texture2D : nullptr);

    if (hr != S_OK)
      return hr;

    *ppTexture2D = static_cast<D3D11Texture2D*>(d3d11Texture2D)->GetD3D10Iface();
    return S_OK;
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::CreateTexture3D(
    const D3D10_TEXTURE3D_DESC*             pDesc,
    const D3D10_SUBRESOURCE_DATA*           pInitialData,
          ID3D10Texture3D**                 ppTexture3D) {
    InitReturnPtr(ppTexture3D);

    if (pDesc == nullptr)
      return E_INVALIDARG;

    D3D11_TEXTURE3D_DESC d3d11Desc;
    d3d11Desc.Width           = pDesc->Width;
    d3d11Desc.Height          = pDesc->Height;
    d3d11Desc.Depth           = pDesc->Depth;
    d3d11Desc.MipLevels       = pDesc->MipLevels;
    d3d11Desc.Format          = pDesc->Format;
    d3d11Desc.Usage           = D3D11_USAGE(pDesc->Usage);
    d3d11Desc.BindFlags       = pDesc->BindFlags;
    d3d11Desc.CPUAccessFlags  = pDesc->CPUAccessFlags;
    d3d11Desc.MiscFlags       = ConvertD3D10ResourceFlags(pDesc->MiscFlags);

    ID3D11Texture3D* d3d11Texture3D = nullptr;
    HRESULT hr = m_device->CreateTexture3D(&d3d11Desc,
      reinterpret_cast<const D3D11_SUBRESOURCE_DATA*>(pInitialData),
      ppTexture3D != nullptr ? &d3d11Texture3D : nullptr);

    if (hr != S_OK)
      return hr;

    *ppTexture3D = static_cast<D3D11Texture3D*>(d3d11Texture3D)->GetD3D10Iface();
    return S_OK;
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::CreateShaderResourceView(
          ID3D10Resource*                   pResource,
    const D3D10_SHADER_RESOURCE_VIEW_DESC*  pDesc,
          ID3D10ShaderResourceView**        ppSRView) {
    InitReturnPtr(ppSRView);

    if (!pResource)
      return E_INVALIDARG;

    Com<ID3D11Resource> d3d11Resource;
    GetD3D11Resource(pResource, &d3d11Resource);

    ID3D11ShaderResourceView* d3d11Srv = nullptr;
    HRESULT hr = m_device->CreateShaderResourceView(d3d11Resource.ptr(),
      reinterpret_cast<const D3D11_SHADER_RESOURCE_VIEW_DESC*>(pDesc),
      ppSRView ? &d3d11Srv : nullptr);

    if (hr != S_OK)
      return hr;

    *ppSRView = static_cast<D3D11ShaderResourceView*>(d3d11Srv)->GetD3D10Iface();
    return S_OK;
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::CreateShaderResourceView1(
          ID3D10Resource*                   pResource,
    const D3D10_SHADER_RESOURCE_VIEW_DESC1* pDesc,
          ID3D10ShaderResourceView1**       ppSRView) {
    InitReturnPtr(ppSRView);

    if (!pResource)
      return E_INVALIDARG;

    Com<ID3D11Resource> d3d11Resource;
    GetD3D11Resource(pResource, &d3d11Resource);

    ID3D11ShaderResourceView* d3d11View = nullptr;
    HRESULT hr = m_device->CreateShaderResourceView(d3d11Resource.ptr(),
      reinterpret_cast<const D3D11_SHADER_RESOURCE_VIEW_DESC*>(pDesc),
      ppSRView ? &d3d11View : nullptr);

    if (hr != S_OK)
      return hr;

    *ppSRView = static_cast<D3D11ShaderResourceView*>(d3d11View)->GetD3D10Iface();
    return S_OK;
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::CreateRenderTargetView(
          ID3D10Resource*                   pResource,
    const D3D10_RENDER_TARGET_VIEW_DESC*    pDesc,
          ID3D10RenderTargetView**          ppRTView) {
    InitReturnPtr(ppRTView);

    if (!pResource)
      return E_INVALIDARG;

    Com<ID3D11Resource> d3d11Resource;
    GetD3D11Resource(pResource, &d3d11Resource);

    ID3D11RenderTargetView* d3d11View = nullptr;
    HRESULT hr = m_device->CreateRenderTargetView(d3d11Resource.ptr(),
      reinterpret_cast<const D3D11_RENDER_TARGET_VIEW_DESC*>(pDesc),
      ppRTView ? &d3d11View : nullptr);

    if (hr != S_OK)
      return hr;

    *ppRTView = static_cast<D3D11RenderTargetView*>(d3d11View)->GetD3D10Iface();
    return S_OK;
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::CreateDepthStencilView(
          ID3D10Resource*                   pResource,
    const D3D10_DEPTH_STENCIL_VIEW_DESC*    pDesc,
          ID3D10DepthStencilView**          ppDepthStencilView) {
    InitReturnPtr(ppDepthStencilView);

    if (!pResource)
      return E_INVALIDARG;

    Com<ID3D11Resource> d3d11Resource;
    GetD3D11Resource(pResource, &d3d11Resource);

    // D3D10 doesn't have the Flags member, so we have
    // to convert the structure. pDesc can be nullptr.
    D3D11_DEPTH_STENCIL_VIEW_DESC d3d11Desc;

    if (pDesc != nullptr) {
      d3d11Desc.ViewDimension         = D3D11_DSV_DIMENSION(pDesc->ViewDimension);
      d3d11Desc.Format                = pDesc->Format;
      d3d11Desc.Flags                 = 0;

      switch (pDesc->ViewDimension) {
        case D3D10_DSV_DIMENSION_UNKNOWN:
          break;

        case D3D10_DSV_DIMENSION_TEXTURE1D:
          d3d11Desc.Texture1D.MipSlice               = pDesc->Texture1D.MipSlice;
          break;

        case D3D10_DSV_DIMENSION_TEXTURE1DARRAY:
          d3d11Desc.Texture1DArray.MipSlice          = pDesc->Texture1DArray.MipSlice;
          d3d11Desc.Texture1DArray.FirstArraySlice   = pDesc->Texture1DArray.FirstArraySlice;
          d3d11Desc.Texture1DArray.ArraySize         = pDesc->Texture1DArray.ArraySize;
          break;

        case D3D10_DSV_DIMENSION_TEXTURE2D:
          d3d11Desc.Texture2D.MipSlice               = pDesc->Texture2D.MipSlice;
          break;

        case D3D10_DSV_DIMENSION_TEXTURE2DARRAY:
          d3d11Desc.Texture2DArray.MipSlice          = pDesc->Texture2DArray.MipSlice;
          d3d11Desc.Texture2DArray.FirstArraySlice   = pDesc->Texture2DArray.FirstArraySlice;
          d3d11Desc.Texture2DArray.ArraySize         = pDesc->Texture2DArray.ArraySize;
          break;

        case D3D10_DSV_DIMENSION_TEXTURE2DMS:
          break;

        case D3D10_DSV_DIMENSION_TEXTURE2DMSARRAY:
          d3d11Desc.Texture2DMSArray.FirstArraySlice = pDesc->Texture2DMSArray.FirstArraySlice;
          d3d11Desc.Texture2DMSArray.ArraySize       = pDesc->Texture2DMSArray.ArraySize;
          break;
      }
    }

    ID3D11DepthStencilView* d3d11View = nullptr;
    HRESULT hr = m_device->CreateDepthStencilView(
      d3d11Resource.ptr(), pDesc ? &d3d11Desc : nullptr,
      ppDepthStencilView ? &d3d11View : nullptr);

    if (hr != S_OK)
      return hr;

    *ppDepthStencilView = static_cast<D3D11DepthStencilView*>(d3d11View)->GetD3D10Iface();
    return S_OK;
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::CreateInputLayout(
    const D3D10_INPUT_ELEMENT_DESC*         pInputElementDescs,
          UINT                              NumElements,
    const void*                             pShaderBytecodeWithInputSignature,
          SIZE_T                            BytecodeLength,
          ID3D10InputLayout**               ppInputLayout) {
    InitReturnPtr(ppInputLayout);

    static_assert(sizeof(D3D10_INPUT_ELEMENT_DESC) ==
                  sizeof(D3D11_INPUT_ELEMENT_DESC));

    ID3D11InputLayout* d3d11InputLayout = nullptr;
    HRESULT hr = m_device->CreateInputLayout(
      reinterpret_cast<const D3D11_INPUT_ELEMENT_DESC*>(pInputElementDescs),
      NumElements, pShaderBytecodeWithInputSignature, BytecodeLength,
      ppInputLayout ? &d3d11InputLayout : nullptr);

    if (hr != S_OK)
      return hr;

    *ppInputLayout = static_cast<D3D11InputLayout*>(d3d11InputLayout)->GetD3D10Iface();
    return hr;
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::CreateVertexShader(
    const void*                             pShaderBytecode,
          SIZE_T                            BytecodeLength,
          ID3D10VertexShader**              ppVertexShader) {
    InitReturnPtr(ppVertexShader);

    ID3D11VertexShader* d3d11Shader = nullptr;

    HRESULT hr = m_device->CreateVertexShader(
      pShaderBytecode, BytecodeLength, nullptr,
      ppVertexShader ? &d3d11Shader : nullptr);

    if (hr != S_OK)
      return hr;

    *ppVertexShader = static_cast<D3D11VertexShader*>(d3d11Shader)->GetD3D10Iface();
    return S_OK;
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::CreateGeometryShader(
    const void*                             pShaderBytecode,
          SIZE_T                            BytecodeLength,
          ID3D10GeometryShader**            ppGeometryShader) {
    InitReturnPtr(ppGeometryShader);

    ID3D11GeometryShader* d3d11Shader = nullptr;

    HRESULT hr = m_device->CreateGeometryShader(
      pShaderBytecode, BytecodeLength, nullptr,
      ppGeometryShader ? &d3d11Shader : nullptr);

    if (hr != S_OK)
      return hr;

    *ppGeometryShader = static_cast<D3D11GeometryShader*>(d3d11Shader)->GetD3D10Iface();
    return S_OK;
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::CreateGeometryShaderWithStreamOutput(
    const void*                             pShaderBytecode,
          SIZE_T                            BytecodeLength,
    const D3D10_SO_DECLARATION_ENTRY*       pSODeclaration,
          UINT                              NumEntries,
          UINT                              OutputStreamStride,
          ID3D10GeometryShader**            ppGeometryShader) {
    InitReturnPtr(ppGeometryShader);

    std::vector<D3D11_SO_DECLARATION_ENTRY> d3d11Entries(NumEntries);

    for (uint32_t i = 0; i < NumEntries; i++) {
      d3d11Entries[i].Stream          = 0;
      d3d11Entries[i].SemanticName    = pSODeclaration[i].SemanticName;
      d3d11Entries[i].SemanticIndex   = pSODeclaration[i].SemanticIndex;
      d3d11Entries[i].StartComponent  = pSODeclaration[i].StartComponent;
      d3d11Entries[i].ComponentCount  = pSODeclaration[i].ComponentCount;
      d3d11Entries[i].OutputSlot      = pSODeclaration[i].OutputSlot;
    }

    ID3D11GeometryShader* d3d11Shader = nullptr;

    HRESULT hr = m_device->CreateGeometryShaderWithStreamOutput(
      pShaderBytecode, BytecodeLength,
      d3d11Entries.data(),
      d3d11Entries.size(),
      &OutputStreamStride, 1,
      D3D11_SO_NO_RASTERIZED_STREAM, nullptr,
      ppGeometryShader ? &d3d11Shader : nullptr);

    if (hr != S_OK)
      return hr;

    *ppGeometryShader = static_cast<D3D11GeometryShader*>(d3d11Shader)->GetD3D10Iface();
    return S_OK;
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::CreatePixelShader(
    const void*                             pShaderBytecode,
          SIZE_T                            BytecodeLength,
          ID3D10PixelShader**               ppPixelShader) {
    InitReturnPtr(ppPixelShader);

    ID3D11PixelShader* d3d11Shader = nullptr;

    HRESULT hr = m_device->CreatePixelShader(
      pShaderBytecode, BytecodeLength, nullptr,
      ppPixelShader ? &d3d11Shader : nullptr);

    if (hr != S_OK)
      return hr;

    *ppPixelShader = static_cast<D3D11PixelShader*>(d3d11Shader)->GetD3D10Iface();
    return S_OK;
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::CreateBlendState(
    const D3D10_BLEND_DESC*                 pBlendStateDesc,
          ID3D10BlendState**                ppBlendState) {
    InitReturnPtr(ppBlendState);

    D3D11_BLEND_DESC d3d11Desc;

    if (pBlendStateDesc != nullptr) {
      d3d11Desc.AlphaToCoverageEnable   = pBlendStateDesc->AlphaToCoverageEnable;
      d3d11Desc.IndependentBlendEnable  = TRUE;

      for (uint32_t i = 0; i < 8; i++) {
        d3d11Desc.RenderTarget[i].BlendEnable           = pBlendStateDesc->BlendEnable[i];
        d3d11Desc.RenderTarget[i].SrcBlend              = D3D11_BLEND   (pBlendStateDesc->SrcBlend);
        d3d11Desc.RenderTarget[i].DestBlend             = D3D11_BLEND   (pBlendStateDesc->DestBlend);
        d3d11Desc.RenderTarget[i].BlendOp               = D3D11_BLEND_OP(pBlendStateDesc->BlendOp);
        d3d11Desc.RenderTarget[i].SrcBlendAlpha         = D3D11_BLEND   (pBlendStateDesc->SrcBlendAlpha);
        d3d11Desc.RenderTarget[i].DestBlendAlpha        = D3D11_BLEND   (pBlendStateDesc->DestBlendAlpha);
        d3d11Desc.RenderTarget[i].BlendOpAlpha          = D3D11_BLEND_OP(pBlendStateDesc->BlendOpAlpha);
        d3d11Desc.RenderTarget[i].RenderTargetWriteMask = pBlendStateDesc->RenderTargetWriteMask[i];
      }
    }

    ID3D11BlendState* d3d11BlendState = nullptr;
    HRESULT hr = m_device->CreateBlendState(&d3d11Desc,
      ppBlendState ? &d3d11BlendState : nullptr);

    if (hr != S_OK)
      return hr;

    *ppBlendState = static_cast<D3D11BlendState*>(d3d11BlendState)->GetD3D10Iface();
    return S_OK;
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::CreateBlendState1(
    const D3D10_BLEND_DESC1*                pBlendStateDesc,
          ID3D10BlendState1**               ppBlendState) {
    InitReturnPtr(ppBlendState);

    ID3D11BlendState* d3d11BlendState = nullptr;
    HRESULT hr = m_device->CreateBlendState(
      reinterpret_cast<const D3D11_BLEND_DESC*>(pBlendStateDesc),
      ppBlendState ? &d3d11BlendState : nullptr);

    if (hr != S_OK)
      return hr;

    *ppBlendState = static_cast<D3D11BlendState*>(d3d11BlendState)->GetD3D10Iface();
    return S_OK;
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::CreateDepthStencilState(
    const D3D10_DEPTH_STENCIL_DESC*         pDepthStencilDesc,
          ID3D10DepthStencilState**         ppDepthStencilState) {
    InitReturnPtr(ppDepthStencilState);

    ID3D11DepthStencilState* d3d11DepthStencilState = nullptr;
    HRESULT hr = m_device->CreateDepthStencilState(
      reinterpret_cast<const D3D11_DEPTH_STENCIL_DESC*>(pDepthStencilDesc),
      ppDepthStencilState ? &d3d11DepthStencilState : nullptr);

    if (hr != S_OK)
      return hr;

    *ppDepthStencilState = static_cast<D3D11DepthStencilState*>(d3d11DepthStencilState)->GetD3D10Iface();
    return S_OK;
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::CreateRasterizerState(
    const D3D10_RASTERIZER_DESC*            pRasterizerDesc,
          ID3D10RasterizerState**           ppRasterizerState) {
    InitReturnPtr(ppRasterizerState);

    ID3D11RasterizerState* d3d11RasterizerState = nullptr;
    HRESULT hr = m_device->CreateRasterizerState(
      reinterpret_cast<const D3D11_RASTERIZER_DESC*>(pRasterizerDesc),
      ppRasterizerState ? &d3d11RasterizerState : nullptr);

    if (hr != S_OK)
      return hr;

    *ppRasterizerState = static_cast<D3D11RasterizerState*>(d3d11RasterizerState)->GetD3D10Iface();
    return S_OK;
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::CreateSamplerState(
    const D3D10_SAMPLER_DESC*               pSamplerDesc,
          ID3D10SamplerState**              ppSamplerState) {
    InitReturnPtr(ppSamplerState);

    if (pSamplerDesc == nullptr)
      return E_INVALIDARG;

    D3D11_SAMPLER_DESC d3d11Desc;
    d3d11Desc.Filter            = D3D11_FILTER(pSamplerDesc->Filter);
    d3d11Desc.AddressU          = D3D11_TEXTURE_ADDRESS_MODE(pSamplerDesc->AddressU);
    d3d11Desc.AddressV          = D3D11_TEXTURE_ADDRESS_MODE(pSamplerDesc->AddressV);
    d3d11Desc.AddressW          = D3D11_TEXTURE_ADDRESS_MODE(pSamplerDesc->AddressW);
    d3d11Desc.MipLODBias        = pSamplerDesc->MipLODBias;
    d3d11Desc.MaxAnisotropy     = pSamplerDesc->MaxAnisotropy;
    d3d11Desc.ComparisonFunc    = D3D11_COMPARISON_FUNC(pSamplerDesc->ComparisonFunc);
    d3d11Desc.MinLOD            = pSamplerDesc->MinLOD;
    d3d11Desc.MaxLOD            = pSamplerDesc->MaxLOD;

    for (uint32_t i = 0; i < 4; i++)
      d3d11Desc.BorderColor[i] = pSamplerDesc->BorderColor[i];

    ID3D11SamplerState* d3d11SamplerState = nullptr;
    HRESULT hr = m_device->CreateSamplerState(&d3d11Desc,
      ppSamplerState ? &d3d11SamplerState : nullptr);

    if (hr != S_OK)
      return hr;

    *ppSamplerState = static_cast<D3D11SamplerState*>(d3d11SamplerState)->GetD3D10Iface();
    return S_OK;
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::CreateQuery(
    const D3D10_QUERY_DESC*                 pQueryDesc,
          ID3D10Query**                     ppQuery) {
    InitReturnPtr(ppQuery);

    if (pQueryDesc == nullptr)
      return E_INVALIDARG;

    D3D11_QUERY_DESC d3d11Desc;
    d3d11Desc.Query      = D3D11_QUERY(pQueryDesc->Query);
    d3d11Desc.MiscFlags  = pQueryDesc->MiscFlags;

    ID3D11Query* d3d11Query = nullptr;
    HRESULT hr = m_device->CreateQuery(&d3d11Desc,
      ppQuery ? &d3d11Query : nullptr);

    if (hr != S_OK)
      return hr;

    *ppQuery = static_cast<D3D11Query*>(d3d11Query)->GetD3D10Iface();
     return S_OK;
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::CreatePredicate(
    const D3D10_QUERY_DESC*                 pPredicateDesc,
          ID3D10Predicate**                 ppPredicate) {
    InitReturnPtr(ppPredicate);

    D3D11_QUERY_DESC d3d11Desc;
    d3d11Desc.Query      = D3D11_QUERY(pPredicateDesc->Query);
    d3d11Desc.MiscFlags  = pPredicateDesc->MiscFlags;

    ID3D11Predicate* d3d11Predicate = nullptr;
    HRESULT hr = m_device->CreatePredicate(&d3d11Desc,
      ppPredicate ? &d3d11Predicate : nullptr);

    if (hr != S_OK)
      return hr;

    *ppPredicate = D3D11Query::FromPredicate(d3d11Predicate)->GetD3D10Iface();
    return S_OK;
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::CreateCounter(
    const D3D10_COUNTER_DESC*               pCounterDesc,
          ID3D10Counter**                   ppCounter) {
    Logger::err("D3D10Device::CreateCounter: Not implemented");
    return E_NOTIMPL;
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::CheckFormatSupport(
          DXGI_FORMAT                       Format,
          UINT*                             pFormatSupport) {
    return m_device->CheckFormatSupport(Format, pFormatSupport);
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::CheckMultisampleQualityLevels(
          DXGI_FORMAT                       Format,
          UINT                              SampleCount,
          UINT*                             pNumQualityLevels) {
    return m_device->CheckMultisampleQualityLevels(
      Format, SampleCount, pNumQualityLevels);
  }

  void STDMETHODCALLTYPE D3D10Device::CheckCounterInfo(
          D3D10_COUNTER_INFO*               pCounterInfo) {
    Logger::err("D3D10Device::CheckCounterInfo: Not implemented");
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::CheckCounter(
    const D3D10_COUNTER_DESC*               pDesc,
          D3D10_COUNTER_TYPE*               pType,
          UINT*                             pActiveCounters,
          char*                             name,
          UINT*                             pNameLength,
          char*                             units,
          UINT*                             pUnitsLength,
          char*                             description,
          UINT*                             pDescriptionLength) {
    Logger::err("D3D10Device::CheckCounter: Not implemented");
    return E_NOTIMPL;
  }

  UINT STDMETHODCALLTYPE D3D10Device::GetCreationFlags() {
    return m_device->GetCreationFlags();
  }

  HRESULT STDMETHODCALLTYPE D3D10Device::OpenSharedResource(
          HANDLE                            hResource,
          REFIID                            ReturnedInterface,
          void**                            ppResource) {
    return m_device->OpenSharedResource(hResource, ReturnedInterface, ppResource);
  }

  void STDMETHODCALLTYPE D3D10Device::ClearRenderTargetView(
          ID3D10RenderTargetView*           pRenderTargetView,
    const FLOAT                             ColorRGBA[4]) {
    D3D10RenderTargetView* d3d10View = static_cast<D3D10RenderTargetView*>(pRenderTargetView);
    D3D11RenderTargetView* d3d11View = d3d10View ? d3d10View->GetD3D11Iface() : nullptr;

    m_context->ClearRenderTargetView(d3d11View, ColorRGBA);
  }

  void STDMETHODCALLTYPE D3D10Device::ClearDepthStencilView(
          ID3D10DepthStencilView*           pDepthStencilView,
          UINT                              ClearFlags,
          FLOAT                             Depth,
          UINT8                             Stencil) {
    D3D10DepthStencilView* d3d10View = static_cast<D3D10DepthStencilView*>(pDepthStencilView);
    D3D11DepthStencilView* d3d11View = d3d10View ? d3d10View->GetD3D11Iface() : nullptr;

    m_context->ClearDepthStencilView(d3d11View, ClearFlags, Depth, Stencil);
  }

  void STDMETHODCALLTYPE D3D10Device::SetPredication(
          ID3D10Predicate*                  pPredicate,
          BOOL                              PredicateValue) {
    D3D10Query* d3d10Predicate = static_cast<D3D10Query*>(pPredicate);
    D3D11Query* d3d11Predicate = d3d10Predicate ? d3d10Predicate->GetD3D11Iface() : nullptr;

    m_context->SetPredication(D3D11Query::AsPredicate(d3d11Predicate), PredicateValue);
  }

  void STDMETHODCALLTYPE D3D10Device::GetPredication(
          ID3D10Predicate**                 ppPredicate,
          BOOL*                             pPredicateValue) {
    ID3D11Predicate* d3d11Predicate = nullptr;

    m_context->GetPredication(
      ppPredicate ? &d3d11Predicate : nullptr,
      pPredicateValue);

    if (ppPredicate)
      *ppPredicate = d3d11Predicate ? D3D11Query::FromPredicate(d3d11Predicate)->GetD3D10Iface() : nullptr;
  }

  void STDMETHODCALLTYPE D3D10Device::CopySubresourceRegion(
          ID3D10Resource*                   pDstResource,
          UINT                              DstSubresource,
          UINT                              DstX,
          UINT                              DstY,
          UINT                              DstZ,
          ID3D10Resource*                   pSrcResource,
          UINT                              SrcSubresource,
    const D3D10_BOX*                        pSrcBox) {
    if (!pDstResource || !pSrcResource)
      return;

    Com<ID3D11Resource> d3d11DstResource;
    Com<ID3D11Resource> d3d11SrcResource;

    GetD3D11Resource(pDstResource, &d3d11DstResource);
    GetD3D11Resource(pSrcResource, &d3d11SrcResource);

    m_context->CopySubresourceRegion(
      d3d11DstResource.ptr(), DstSubresource, DstX, DstY, DstZ,
      d3d11SrcResource.ptr(), SrcSubresource,
      reinterpret_cast<const D3D11_BOX*>(pSrcBox));
  }

  void STDMETHODCALLTYPE D3D10Device::CopyResource(
          ID3D10Resource*                   pDstResource,
          ID3D10Resource*                   pSrcResource) {
    if (!pDstResource || !pSrcResource)
      return;

    Com<ID3D11Resource> d3d11DstResource;
    Com<ID3D11Resource> d3d11SrcResource;

    GetD3D11Resource(pDstResource, &d3d11DstResource);
    GetD3D11Resource(pSrcResource, &d3d11SrcResource);

    m_context->CopyResource(
      d3d11DstResource.ptr(),
      d3d11SrcResource.ptr());
  }

  void STDMETHODCALLTYPE D3D10Device::UpdateSubresource(
          ID3D10Resource*                   pDstResource,
          UINT                              DstSubresource,
    const D3D10_BOX*                        pDstBox,
    const void*                             pSrcData,
          UINT                              SrcRowPitch,
          UINT                              SrcDepthPitch) {
    if (!pDstResource)
      return;

    Com<ID3D11Resource> d3d11DstResource;
    GetD3D11Resource(pDstResource, &d3d11DstResource);

    m_context->UpdateSubresource(
      d3d11DstResource.ptr(), DstSubresource,
      reinterpret_cast<const D3D11_BOX*>(pDstBox),
      pSrcData, SrcRowPitch, SrcDepthPitch);
  }

  void STDMETHODCALLTYPE D3D10Device::GenerateMips(
          ID3D10ShaderResourceView*         pShaderResourceView) {
    D3D10ShaderResourceView* d3d10View = static_cast<D3D10ShaderResourceView*>(pShaderResourceView);
    D3D11ShaderResourceView* d3d11View = d3d10View ? d3d10View->GetD3D11Iface() : nullptr;

    m_context->GenerateMips(d3d11View);
  }

  void STDMETHODCALLTYPE D3D10Device::ResolveSubresource(
          ID3D10Resource*                   pDstResource,
          UINT                              DstSubresource,
          ID3D10Resource*                   pSrcResource,
          UINT                              SrcSubresource,
          DXGI_FORMAT                       Format) {
    if (!pDstResource || !pSrcResource)
      return;

    Com<ID3D11Resource> d3d11DstResource;
    Com<ID3D11Resource> d3d11SrcResource;

    GetD3D11Resource(pDstResource, &d3d11DstResource);
    GetD3D11Resource(pSrcResource, &d3d11SrcResource);

    m_context->ResolveSubresource(
      d3d11DstResource.ptr(), DstSubresource,
      d3d11SrcResource.ptr(), SrcSubresource,
      Format);
  }

  void STDMETHODCALLTYPE D3D10Device::Draw(
          UINT                              VertexCount,
          UINT                              StartVertexLocation) {
    m_context->Draw(VertexCount,
      StartVertexLocation);
  }

  void STDMETHODCALLTYPE D3D10Device::DrawIndexed(
          UINT                              IndexCount,
          UINT                              StartIndexLocation,
          INT                               BaseVertexLocation) {
    m_context->DrawIndexed(IndexCount,
      StartIndexLocation,
      BaseVertexLocation);
  }

  void STDMETHODCALLTYPE D3D10Device::DrawInstanced(
          UINT                              VertexCountPerInstance,
          UINT                              InstanceCount,
          UINT                              StartVertexLocation,
          UINT                              StartInstanceLocation) {
    m_context->DrawInstanced(
      VertexCountPerInstance,
      InstanceCount,
      StartVertexLocation,
      StartInstanceLocation);
  }

  void STDMETHODCALLTYPE D3D10Device::DrawIndexedInstanced(
          UINT                              IndexCountPerInstance,
          UINT                              InstanceCount,
          UINT                              StartIndexLocation,
          INT                               BaseVertexLocation,
          UINT                              StartInstanceLocation) {
    m_context->DrawIndexedInstanced(
      IndexCountPerInstance,
      InstanceCount,
      StartIndexLocation,
      BaseVertexLocation,
      StartInstanceLocation);
  }

  void STDMETHODCALLTYPE D3D10Device::DrawAuto() {
    m_context->DrawAuto();
  }

  void STDMETHODCALLTYPE D3D10Device::IASetInputLayout(
          ID3D10InputLayout*                pInputLayout) {
    D3D10InputLayout* d3d10InputLayout = static_cast<D3D10InputLayout*>(pInputLayout);
    D3D11InputLayout* d3d11InputLayout = d3d10InputLayout ? d3d10InputLayout->GetD3D11Iface() : nullptr;

    m_context->IASetInputLayout(d3d11InputLayout);
  }

  void STDMETHODCALLTYPE D3D10Device::IASetPrimitiveTopology(
          D3D10_PRIMITIVE_TOPOLOGY          Topology) {
    m_context->IASetPrimitiveTopology(
      D3D11_PRIMITIVE_TOPOLOGY(Topology));
  }

  void STDMETHODCALLTYPE D3D10Device::IASetVertexBuffers(
          UINT                              StartSlot,
          UINT                              NumBuffers,
          ID3D10Buffer* const*              ppVertexBuffers,
    const UINT*                             pStrides,
    const UINT*                             pOffsets) {
    ID3D11Buffer* d3d11Buffers[D3D10_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];

    if (NumBuffers > D3D10_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT)
      return;

    for (uint32_t i = 0; i < NumBuffers; i++) {
      d3d11Buffers[i] = ppVertexBuffers[i]
        ? static_cast<D3D10Buffer*>(ppVertexBuffers[i])->GetD3D11Iface()
        : nullptr;
    }

    m_context->IASetVertexBuffers(
      StartSlot, NumBuffers, d3d11Buffers,
      pStrides, pOffsets);
  }

  void STDMETHODCALLTYPE D3D10Device::IASetIndexBuffer(
          ID3D10Buffer*                     pIndexBuffer,
          DXGI_FORMAT                       Format,
          UINT                              Offset) {
    D3D10Buffer* d3d10Buffer = static_cast<D3D10Buffer*>(pIndexBuffer);
    D3D11Buffer* d3d11Buffer = d3d10Buffer ? d3d10Buffer->GetD3D11Iface() : nullptr;

    m_context->IASetIndexBuffer(d3d11Buffer, Format, Offset);
  }

  void STDMETHODCALLTYPE D3D10Device::IAGetInputLayout(
          ID3D10InputLayout**               ppInputLayout) {
    ID3D11InputLayout* d3d11InputLayout = nullptr;
    m_context->IAGetInputLayout(&d3d11InputLayout);

    *ppInputLayout = d3d11InputLayout
      ? static_cast<D3D11InputLayout*>(d3d11InputLayout)->GetD3D10Iface()
      : nullptr;
  }

  void STDMETHODCALLTYPE D3D10Device::IAGetPrimitiveTopology(
          D3D10_PRIMITIVE_TOPOLOGY*         pTopology) {
    D3D11_PRIMITIVE_TOPOLOGY d3d11Topology;
    m_context->IAGetPrimitiveTopology(&d3d11Topology);

    *pTopology = d3d11Topology <= 32 /* begin patch list */
      ? D3D10_PRIMITIVE_TOPOLOGY(d3d11Topology)
      : D3D10_PRIMITIVE_TOPOLOGY_UNDEFINED;
  }

  void STDMETHODCALLTYPE D3D10Device::IAGetVertexBuffers(
          UINT                              StartSlot,
          UINT                              NumBuffers,
          ID3D10Buffer**                    ppVertexBuffers,
          UINT*                             pStrides,
          UINT*                             pOffsets) {
    ID3D11Buffer* d3d11Buffers[D3D10_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT];

    m_context->IAGetVertexBuffers(
      StartSlot, NumBuffers,
      ppVertexBuffers ? d3d11Buffers : nullptr,
      pStrides, pOffsets);

    if (ppVertexBuffers) {
      for (uint32_t i = 0; i < NumBuffers; i++) {
        ppVertexBuffers[i] = d3d11Buffers[i]
          ? static_cast<D3D11Buffer*>(d3d11Buffers[i])->GetD3D10Iface()
          : nullptr;
      }
    }
  }

  void STDMETHODCALLTYPE D3D10Device::IAGetIndexBuffer(
          ID3D10Buffer**                    pIndexBuffer,
          DXGI_FORMAT*                      Format,
          UINT*                             Offset) {
    ID3D11Buffer* d3d11Buffer = nullptr;

    m_context->IAGetIndexBuffer(
      pIndexBuffer ? &d3d11Buffer : nullptr,
      Format, Offset);

    if (pIndexBuffer)
      *pIndexBuffer = d3d11Buffer ? static_cast<D3D11Buffer*>(d3d11Buffer)->GetD3D10Iface() : nullptr;
  }

  void STDMETHODCALLTYPE D3D10Device::VSSetShader(
          ID3D10VertexShader*               pVertexShader) {
    D3D10VertexShader* d3d10Shader = static_cast<D3D10VertexShader*>(pVertexShader);
    D3D11VertexShader* d3d11Shader = d3d10Shader ? d3d10Shader->GetD3D11Iface() : nullptr;

    m_context->VSSetShader(d3d11Shader, nullptr, 0);
  }

  void STDMETHODCALLTYPE D3D10Device::VSSetConstantBuffers(
          UINT                              StartSlot,
          UINT                              NumBuffers,
          ID3D10Buffer* const*              ppConstantBuffers) {
    ID3D11Buffer* d3d11Buffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];

    if (NumBuffers > D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT)
      return;

    for (uint32_t i = 0; i < NumBuffers; i++) {
      d3d11Buffers[i] = ppConstantBuffers && ppConstantBuffers[i]
        ? static_cast<D3D10Buffer*>(ppConstantBuffers[i])->GetD3D11Iface()
        : nullptr;
    }

    m_context->VSSetConstantBuffers(StartSlot, NumBuffers, d3d11Buffers);
  }

  void STDMETHODCALLTYPE D3D10Device::VSSetShaderResources(
          UINT                              StartSlot,
          UINT                              NumViews,
          ID3D10ShaderResourceView* const*  ppShaderResourceViews) {
    ID3D11ShaderResourceView* d3d11Views[D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];

    if (NumViews > D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT)
      return;

    for (uint32_t i = 0; i < NumViews; i++) {
      d3d11Views[i] = ppShaderResourceViews && ppShaderResourceViews[i]
        ? static_cast<D3D10ShaderResourceView*>(ppShaderResourceViews[i])->GetD3D11Iface()
        : nullptr;
    }

    m_context->VSSetShaderResources(StartSlot, NumViews, d3d11Views);
  }

  void STDMETHODCALLTYPE D3D10Device::VSSetSamplers(
          UINT                              StartSlot,
          UINT                              NumSamplers,
          ID3D10SamplerState* const*        ppSamplers) {
    ID3D11SamplerState* d3d11Samplers[D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT];

    if (NumSamplers > D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT)
      return;

    for (uint32_t i = 0; i < NumSamplers; i++) {
      d3d11Samplers[i] = ppSamplers && ppSamplers[i]
        ? static_cast<D3D10SamplerState*>(ppSamplers[i])->GetD3D11Iface()
        : nullptr;
    }

    m_context->VSSetSamplers(StartSlot, NumSamplers, d3d11Samplers);
  }

  void STDMETHODCALLTYPE D3D10Device::VSGetShader(
          ID3D10VertexShader**              ppVertexShader) {
    ID3D11VertexShader* d3d11Shader = nullptr;
    m_context->VSGetShader(&d3d11Shader, nullptr, nullptr);

    *ppVertexShader = d3d11Shader ? static_cast<D3D11VertexShader*>(d3d11Shader)->GetD3D10Iface() : nullptr;
  }

  void STDMETHODCALLTYPE D3D10Device::VSGetConstantBuffers(
          UINT                              StartSlot,
          UINT                              NumBuffers,
          ID3D10Buffer**                    ppConstantBuffers) {
    ID3D11Buffer* d3d11Buffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];
    m_context->VSGetConstantBuffers(StartSlot, NumBuffers, d3d11Buffers);

    for (uint32_t i = 0; i < NumBuffers; i++) {
      ppConstantBuffers[i] = d3d11Buffers[i]
        ? static_cast<D3D11Buffer*>(d3d11Buffers[i])->GetD3D10Iface()
        : nullptr;
    }
  }

  void STDMETHODCALLTYPE D3D10Device::VSGetShaderResources(
          UINT                              StartSlot,
          UINT                              NumViews,
          ID3D10ShaderResourceView**        ppShaderResourceViews) {
    ID3D11ShaderResourceView* d3d11Views[D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];
    m_context->VSGetShaderResources(StartSlot, NumViews, d3d11Views);

    for (uint32_t i = 0; i < NumViews; i++) {
      ppShaderResourceViews[i] = d3d11Views[i]
        ? static_cast<D3D11ShaderResourceView*>(d3d11Views[i])->GetD3D10Iface()
        : nullptr;
    }
  }

  void STDMETHODCALLTYPE D3D10Device::VSGetSamplers(
          UINT                              StartSlot,
          UINT                              NumSamplers,
          ID3D10SamplerState**              ppSamplers) {
    ID3D11SamplerState* d3d11Samplers[D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT];
    m_context->VSGetSamplers(StartSlot, NumSamplers, d3d11Samplers);

    for (uint32_t i = 0; i < NumSamplers; i++) {
      ppSamplers[i] = d3d11Samplers[i]
        ? static_cast<D3D11SamplerState*>(d3d11Samplers[i])->GetD3D10Iface()
        : nullptr;
    }
  }

  void STDMETHODCALLTYPE D3D10Device::GSSetShader(
          ID3D10GeometryShader*             pShader) {
    D3D10GeometryShader* d3d10Shader = static_cast<D3D10GeometryShader*>(pShader);
    D3D11GeometryShader* d3d11Shader = d3d10Shader ? d3d10Shader->GetD3D11Iface() : nullptr;

    m_context->GSSetShader(d3d11Shader, nullptr, 0);
  }

  void STDMETHODCALLTYPE D3D10Device::GSSetConstantBuffers(
          UINT                              StartSlot,
          UINT                              NumBuffers,
          ID3D10Buffer* const*              ppConstantBuffers) {
    ID3D11Buffer* d3d11Buffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];

    if (NumBuffers > D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT)
      return;

    for (uint32_t i = 0; i < NumBuffers; i++) {
      d3d11Buffers[i] = ppConstantBuffers && ppConstantBuffers[i]
        ? static_cast<D3D10Buffer*>(ppConstantBuffers[i])->GetD3D11Iface()
        : nullptr;
    }

    m_context->GSSetConstantBuffers(StartSlot, NumBuffers, d3d11Buffers);
  }

  void STDMETHODCALLTYPE D3D10Device::GSSetShaderResources(
          UINT                              StartSlot,
          UINT                              NumViews,
          ID3D10ShaderResourceView* const*  ppShaderResourceViews) {
    ID3D11ShaderResourceView* d3d11Views[D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];

    if (NumViews > D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT)
      return;

    for (uint32_t i = 0; i < NumViews; i++) {
      d3d11Views[i] = ppShaderResourceViews && ppShaderResourceViews[i]
        ? static_cast<D3D10ShaderResourceView*>(ppShaderResourceViews[i])->GetD3D11Iface()
        : nullptr;
    }

    m_context->GSSetShaderResources(StartSlot, NumViews, d3d11Views);
  }

  void STDMETHODCALLTYPE D3D10Device::GSSetSamplers(
          UINT                              StartSlot,
          UINT                              NumSamplers,
          ID3D10SamplerState* const*        ppSamplers) {
    ID3D11SamplerState* d3d11Samplers[D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT];

    if (NumSamplers > D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT)
      return;

    for (uint32_t i = 0; i < NumSamplers; i++) {
      d3d11Samplers[i] = ppSamplers && ppSamplers[i]
        ? static_cast<D3D10SamplerState*>(ppSamplers[i])->GetD3D11Iface()
        : nullptr;
    }

    m_context->GSSetSamplers(StartSlot, NumSamplers, d3d11Samplers);
  }

  void STDMETHODCALLTYPE D3D10Device::GSGetShader(
          ID3D10GeometryShader**            ppGeometryShader) {
    ID3D11GeometryShader* d3d11Shader = nullptr;
    m_context->GSGetShader(&d3d11Shader, nullptr, nullptr);

    *ppGeometryShader = d3d11Shader ? static_cast<D3D11GeometryShader*>(d3d11Shader)->GetD3D10Iface() : nullptr;
  }

  void STDMETHODCALLTYPE D3D10Device::GSGetConstantBuffers(
          UINT                              StartSlot,
          UINT                              NumBuffers,
          ID3D10Buffer**                    ppConstantBuffers) {
    ID3D11Buffer* d3d11Buffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];
    m_context->GSGetConstantBuffers(StartSlot, NumBuffers, d3d11Buffers);

    for (uint32_t i = 0; i < NumBuffers; i++) {
      ppConstantBuffers[i] = d3d11Buffers[i]
        ? static_cast<D3D11Buffer*>(d3d11Buffers[i])->GetD3D10Iface()
        : nullptr;
    }
  }

  void STDMETHODCALLTYPE D3D10Device::GSGetShaderResources(
          UINT                              StartSlot,
          UINT                              NumViews,
          ID3D10ShaderResourceView**        ppShaderResourceViews) {
    ID3D11ShaderResourceView* d3d11Views[D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];
    m_context->GSGetShaderResources(StartSlot, NumViews, d3d11Views);

    for (uint32_t i = 0; i < NumViews; i++) {
      ppShaderResourceViews[i] = d3d11Views[i]
        ? static_cast<D3D11ShaderResourceView*>(d3d11Views[i])->GetD3D10Iface()
        : nullptr;
    }
  }

  void STDMETHODCALLTYPE D3D10Device::GSGetSamplers(
          UINT                              StartSlot,
          UINT                              NumSamplers,
          ID3D10SamplerState**              ppSamplers) {
    ID3D11SamplerState* d3d11Samplers[D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT];
    m_context->GSGetSamplers(StartSlot, NumSamplers, d3d11Samplers);

    for (uint32_t i = 0; i < NumSamplers; i++) {
      ppSamplers[i] = d3d11Samplers[i]
        ? static_cast<D3D11SamplerState*>(d3d11Samplers[i])->GetD3D10Iface()
        : nullptr;
    }
  }

  void STDMETHODCALLTYPE D3D10Device::PSSetShader(
          ID3D10PixelShader*                pPixelShader) {
    D3D10PixelShader* d3d10Shader = static_cast<D3D10PixelShader*>(pPixelShader);
    D3D11PixelShader* d3d11Shader = d3d10Shader ? d3d10Shader->GetD3D11Iface() : nullptr;

    m_context->PSSetShader(d3d11Shader, nullptr, 0);
  }

  void STDMETHODCALLTYPE D3D10Device::PSSetConstantBuffers(
          UINT                              StartSlot,
          UINT                              NumBuffers,
          ID3D10Buffer* const*              ppConstantBuffers) {
    ID3D11Buffer* d3d11Buffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];

    if (NumBuffers > D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT)
      return;

    for (uint32_t i = 0; i < NumBuffers; i++) {
      d3d11Buffers[i] = ppConstantBuffers && ppConstantBuffers[i]
        ? static_cast<D3D10Buffer*>(ppConstantBuffers[i])->GetD3D11Iface()
        : nullptr;
    }

    m_context->PSSetConstantBuffers(StartSlot, NumBuffers, d3d11Buffers);
  }

  void STDMETHODCALLTYPE D3D10Device::PSSetShaderResources(
          UINT                              StartSlot,
          UINT                              NumViews,
          ID3D10ShaderResourceView* const*  ppShaderResourceViews) {
    ID3D11ShaderResourceView* d3d11Views[D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];

    if (NumViews > D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT)
      return;

    for (uint32_t i = 0; i < NumViews; i++) {
      d3d11Views[i] = ppShaderResourceViews && ppShaderResourceViews[i]
        ? static_cast<D3D10ShaderResourceView*>(ppShaderResourceViews[i])->GetD3D11Iface()
        : nullptr;
    }

    m_context->PSSetShaderResources(StartSlot, NumViews, d3d11Views);
  }

  void STDMETHODCALLTYPE D3D10Device::PSSetSamplers(
          UINT                              StartSlot,
          UINT                              NumSamplers,
          ID3D10SamplerState* const*        ppSamplers) {
    ID3D11SamplerState* d3d11Samplers[D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT];

    if (NumSamplers > D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT)
      return;

    for (uint32_t i = 0; i < NumSamplers; i++) {
      d3d11Samplers[i] = ppSamplers && ppSamplers[i]
        ? static_cast<D3D10SamplerState*>(ppSamplers[i])->GetD3D11Iface()
        : nullptr;
    }

    m_context->PSSetSamplers(StartSlot, NumSamplers, d3d11Samplers);
  }

  void STDMETHODCALLTYPE D3D10Device::PSGetShader(
          ID3D10PixelShader**               ppPixelShader) {
    ID3D11PixelShader* d3d11Shader = nullptr;
    m_context->PSGetShader(&d3d11Shader, nullptr, nullptr);

    *ppPixelShader = d3d11Shader ? static_cast<D3D11PixelShader*>(d3d11Shader)->GetD3D10Iface() : nullptr;
  }

  void STDMETHODCALLTYPE D3D10Device::PSGetConstantBuffers(
          UINT                              StartSlot,
          UINT                              NumBuffers,
          ID3D10Buffer**                    ppConstantBuffers) {
    ID3D11Buffer* d3d11Buffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT];
    m_context->PSGetConstantBuffers(StartSlot, NumBuffers, d3d11Buffers);

    for (uint32_t i = 0; i < NumBuffers; i++) {
      ppConstantBuffers[i] = d3d11Buffers[i]
        ? static_cast<D3D11Buffer*>(d3d11Buffers[i])->GetD3D10Iface()
        : nullptr;
    }
  }

  void STDMETHODCALLTYPE D3D10Device::PSGetShaderResources(
          UINT                              StartSlot,
          UINT                              NumViews,
          ID3D10ShaderResourceView**        ppShaderResourceViews) {
    ID3D11ShaderResourceView* d3d11Views[D3D10_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT];
    m_context->PSGetShaderResources(StartSlot, NumViews, d3d11Views);

    for (uint32_t i = 0; i < NumViews; i++) {
      ppShaderResourceViews[i] = d3d11Views[i]
        ? static_cast<D3D11ShaderResourceView*>(d3d11Views[i])->GetD3D10Iface()
        : nullptr;
    }
  }

  void STDMETHODCALLTYPE D3D10Device::PSGetSamplers(
          UINT                              StartSlot,
          UINT                              NumSamplers,
          ID3D10SamplerState**              ppSamplers) {
    ID3D11SamplerState* d3d11Samplers[D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT];
    m_context->PSGetSamplers(StartSlot, NumSamplers, d3d11Samplers);

    for (uint32_t i = 0; i < NumSamplers; i++) {
      ppSamplers[i] = d3d11Samplers[i]
        ? static_cast<D3D11SamplerState*>(d3d11Samplers[i])->GetD3D10Iface()
        : nullptr;
    }
  }

  void STDMETHODCALLTYPE D3D10Device::OMSetRenderTargets(
          UINT                              NumViews,
          ID3D10RenderTargetView* const*    ppRenderTargetViews,
          ID3D10DepthStencilView*           pDepthStencilView) {
    ID3D11RenderTargetView* d3d11Rtv[D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT];

    if (NumViews > D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT)
      return;

    for (uint32_t i = 0; i < NumViews; i++) {
      d3d11Rtv[i] = ppRenderTargetViews && ppRenderTargetViews[i]
        ? static_cast<D3D10RenderTargetView*>(ppRenderTargetViews[i])->GetD3D11Iface()
        : nullptr;
    }

    D3D10DepthStencilView* d3d10Dsv = static_cast<D3D10DepthStencilView*>(pDepthStencilView);
    D3D11DepthStencilView* d3d11Dsv = d3d10Dsv ? d3d10Dsv->GetD3D11Iface() : nullptr;

    m_context->OMSetRenderTargets(NumViews, d3d11Rtv, d3d11Dsv);
  }

  void STDMETHODCALLTYPE D3D10Device::OMSetBlendState(
          ID3D10BlendState*                 pBlendState,
    const FLOAT                             BlendFactor[4],
          UINT                              SampleMask) {
    D3D10BlendState* d3d10BlendState = static_cast<D3D10BlendState*>(pBlendState);
    D3D11BlendState* d3d11BlendState = d3d10BlendState ? d3d10BlendState->GetD3D11Iface() : nullptr;

    m_context->OMSetBlendState(d3d11BlendState, BlendFactor, SampleMask);
  }

  void STDMETHODCALLTYPE D3D10Device::OMSetDepthStencilState(
          ID3D10DepthStencilState*          pDepthStencilState,
          UINT                              StencilRef) {
    D3D10DepthStencilState* d3d10DepthStencilState = static_cast<D3D10DepthStencilState*>(pDepthStencilState);
    D3D11DepthStencilState* d3d11DepthStencilState = d3d10DepthStencilState ? d3d10DepthStencilState->GetD3D11Iface() : nullptr;

    m_context->OMSetDepthStencilState(d3d11DepthStencilState, StencilRef);
  }

  void STDMETHODCALLTYPE D3D10Device::OMGetRenderTargets(
          UINT                              NumViews,
          ID3D10RenderTargetView**          ppRenderTargetViews,
          ID3D10DepthStencilView**          ppDepthStencilView) {
    ID3D11RenderTargetView* d3d11Rtv[D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT];
    ID3D11DepthStencilView* d3d11Dsv = nullptr;

    m_context->OMGetRenderTargets(NumViews,
      ppRenderTargetViews ? d3d11Rtv : nullptr,
      ppDepthStencilView ? &d3d11Dsv : nullptr);

    if (ppRenderTargetViews != nullptr) {
      for (uint32_t i = 0; i < NumViews; i++) {
        ppRenderTargetViews[i] = d3d11Rtv[i]
          ? static_cast<D3D11RenderTargetView*>(d3d11Rtv[i])->GetD3D10Iface()
          : nullptr;
      }
    }

    if (ppDepthStencilView)
      *ppDepthStencilView = d3d11Dsv ? static_cast<D3D11DepthStencilView*>(d3d11Dsv)->GetD3D10Iface() : nullptr;
  }

  void STDMETHODCALLTYPE D3D10Device::OMGetBlendState(
          ID3D10BlendState**                ppBlendState,
          FLOAT                             BlendFactor[4],
          UINT*                             pSampleMask) {
    ID3D11BlendState* d3d11BlendState = nullptr;

    m_context->OMGetBlendState(
      ppBlendState ? &d3d11BlendState : nullptr,
      BlendFactor, pSampleMask);

    if (ppBlendState != nullptr)
      *ppBlendState = d3d11BlendState ? static_cast<D3D11BlendState*>(d3d11BlendState)->GetD3D10Iface() : nullptr;
  }

  void STDMETHODCALLTYPE D3D10Device::OMGetDepthStencilState(
          ID3D10DepthStencilState**         ppDepthStencilState,
          UINT*                             pStencilRef) {
    ID3D11DepthStencilState* d3d11DepthStencilState = nullptr;

    m_context->OMGetDepthStencilState(
      ppDepthStencilState ? &d3d11DepthStencilState : nullptr,
      pStencilRef);

    if (ppDepthStencilState != nullptr)
      *ppDepthStencilState = d3d11DepthStencilState ? static_cast<D3D11DepthStencilState*>(d3d11DepthStencilState)->GetD3D10Iface() : nullptr;
  }

  void STDMETHODCALLTYPE D3D10Device::RSSetState(
          ID3D10RasterizerState*            pRasterizerState) {
    D3D10RasterizerState* d3d10RasterizerState = static_cast<D3D10RasterizerState*>(pRasterizerState);
    D3D11RasterizerState* d3d11RasterizerState = d3d10RasterizerState ? d3d10RasterizerState->GetD3D11Iface() : nullptr;

    m_context->RSSetState(d3d11RasterizerState);
  }

  void STDMETHODCALLTYPE D3D10Device::RSSetViewports(
          UINT                              NumViewports,
    const D3D10_VIEWPORT*                   pViewports) {
    D3D11_VIEWPORT vp[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];

    if (NumViewports > D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE)
      return;

    for (uint32_t i = 0; i < NumViewports; i++) {
      vp[i].TopLeftX = float(pViewports[i].TopLeftX);
      vp[i].TopLeftY = float(pViewports[i].TopLeftY);
      vp[i].Width    = float(pViewports[i].Width);
      vp[i].Height   = float(pViewports[i].Height);
      vp[i].MinDepth = pViewports[i].MinDepth;
      vp[i].MaxDepth = pViewports[i].MaxDepth;
    }

    m_context->RSSetViewports(NumViewports, vp);
  }

  void STDMETHODCALLTYPE D3D10Device::RSSetScissorRects(
          UINT                              NumRects,
    const D3D10_RECT*                       pRects) {
    m_context->RSSetScissorRects(NumRects, pRects);
  }

  void STDMETHODCALLTYPE D3D10Device::RSGetState(
          ID3D10RasterizerState**           ppRasterizerState) {
    ID3D11RasterizerState* d3d11RasterizerState = nullptr;
    m_context->RSGetState(&d3d11RasterizerState);

    *ppRasterizerState = d3d11RasterizerState ? static_cast<D3D11RasterizerState*>(d3d11RasterizerState)->GetD3D10Iface() : nullptr;
  }

  void STDMETHODCALLTYPE D3D10Device::RSGetViewports(
          UINT*                             NumViewports,
          D3D10_VIEWPORT*                   pViewports) {
    D3D11_VIEWPORT vp[D3D10_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE];
    m_context->RSGetViewports(NumViewports, pViewports != nullptr ? vp : nullptr);

    if (pViewports != nullptr) {
      for (uint32_t i = 0; i < *NumViewports; i++) {
        pViewports[i].TopLeftX = int32_t(vp[i].TopLeftX);
        pViewports[i].TopLeftY = int32_t(vp[i].TopLeftY);
        pViewports[i].Width    = uint32_t(vp[i].Width);
        pViewports[i].Height   = uint32_t(vp[i].Height);
        pViewports[i].MinDepth = vp[i].MinDepth;
        pViewports[i].MaxDepth = vp[i].MaxDepth;
      }
    }
  }

  void STDMETHODCALLTYPE D3D10Device::RSGetScissorRects(
          UINT*                             NumRects,
          D3D10_RECT*                       pRects) {
    m_context->RSGetScissorRects(NumRects, pRects);
  }

  void STDMETHODCALLTYPE D3D10Device::SOSetTargets(
          UINT                              NumBuffers,
          ID3D10Buffer* const*              ppSOTargets,
    const UINT*                             pOffsets) {
    ID3D11Buffer* d3d11Buffers[D3D10_SO_BUFFER_SLOT_COUNT];

    if (NumBuffers > D3D10_SO_BUFFER_SLOT_COUNT)
      return;

    for (uint32_t i = 0; i < NumBuffers; i++) {
      d3d11Buffers[i] = ppSOTargets && ppSOTargets[i]
        ? static_cast<D3D10Buffer*>(ppSOTargets[i])->GetD3D11Iface()
        : nullptr;
    }

    m_context->SOSetTargets(NumBuffers, d3d11Buffers, pOffsets);
  }

  void STDMETHODCALLTYPE D3D10Device::SOGetTargets(
          UINT                              NumBuffers,
          ID3D10Buffer**                    ppSOTargets,
          UINT*                             pOffsets) {
    ID3D11Buffer* d3d11Buffers[D3D10_SO_BUFFER_SLOT_COUNT];

    m_context->SOGetTargetsWithOffsets(NumBuffers,
      ppSOTargets ? d3d11Buffers : nullptr,
      pOffsets);

    if (ppSOTargets != nullptr) {
      for (uint32_t i = 0; i < NumBuffers; i++) {
        ppSOTargets[i] = d3d11Buffers[i]
          ? static_cast<D3D11Buffer*>(d3d11Buffers[i])->GetD3D10Iface()
          : nullptr;
      }
    }
  }

  void STDMETHODCALLTYPE D3D10Device::SetTextFilterSize(
          UINT                              Width,
          UINT                              Height) {
    // D3D10 doesn't seem to actually store or do anything with these values,
    // as when calling GetTextFilterSize, it just makes the values 0.
  }

  void STDMETHODCALLTYPE D3D10Device::GetTextFilterSize(
          UINT*                             pWidth,
          UINT*                             pHeight) {
    if (pWidth)
        *pWidth = 0;

    if (pHeight)
        *pHeight = 0;
  }

}