0
0
mirror of https://github.com/mpv-player/mpv.git synced 2024-09-20 03:52:22 +02:00

vo_gpu: d3d11: initial implementation

This is a new RA/vo_gpu backend that uses Direct3D 11. The GLSL
generated by vo_gpu is cross-compiled to HLSL with SPIRV-Cross.

What works:

- All of mpv's internal shaders should work, including compute shaders.

- Some external shaders have been tested and work, including RAVU and
  adaptive-sharpen.

- Non-dumb mode works, even on very old hardware. Most features work at
  feature level 9_3 and all features work at feature level 10_0. Some
  features also work at feature level 9_1 and 9_2, but without high-bit-
  depth FBOs, it's not very useful. (Hardware this old is probably not
  fast enough for advanced features anyway.)

  Note: This is more compatible than ANGLE, which requires 9_3 to work
  at all (GLES 2.0,) and 10_1 for non-dumb-mode (GLES 3.0.)

- Hardware decoding with D3D11VA, including decoding of 10-bit formats
  without truncation to 8-bit.

What doesn't work / can be improved:

- PBO upload and direct rendering does not work yet. Direct rendering
  requires persistent-mapped PBOs because the decoder needs to be able
  to read data from images that have already been decoded and uploaded.
  Unfortunately, it seems like persistent-mapped PBOs are fundamentally
  incompatible with D3D11, which requires all resources to use driver-
  managed memory and requires memory to be unmapped (and hence pointers
  to be invalidated) when a resource is used in a draw or copy
  operation.

  However it might be possible to use D3D11's limited multithreading
  capabilities to emulate some features of PBOs, like asynchronous
  texture uploading.

- The blit() and clear() operations don't have equivalents in the D3D11
  API that handle all cases, so in most cases, they have to be emulated
  with a shader. This is currently done inside ra_d3d11, but ideally it
  would be done in generic code, so it can take advantage of mpv's
  shader generation utilities.

- SPIRV-Cross is used through a NIH C-compatible wrapper library, since
  it does not expose a C interface itself.

  The library is available here: https://github.com/rossy/crossc

- The D3D11 context could be made to support more modern DXGI features
  in future. For example, it should be possible to add support for
  high-bit-depth and HDR output with DXGI 1.5/1.6.
This commit is contained in:
James Ross-Gowan 2017-09-07 20:18:06 +10:00
parent 8020a62953
commit 68eac1a1e7
14 changed files with 2797 additions and 16 deletions

View File

@ -686,8 +686,8 @@ Video
:dxva2: requires ``--vo=gpu`` with ``--gpu-context=angle`` or
``--gpu-context=dxinterop`` (Windows only)
:dxva2-copy: copies video back to system RAM (Windows only)
:d3d11va: requires ``--vo=gpu`` with ``--gpu-context=angle``
(Windows 8+ only)
:d3d11va: requires ``--vo=gpu`` with ``--gpu-context=d3d11`` or
``--gpu-context=angle`` (Windows 8+ only)
:d3d11va-copy: copies video back to system RAM (Windows 8+ only)
:mediacodec: requires ``--vo=mediacodec_embed`` (Android only)
:mediacodec-copy: copies video back to system RAM (Android only)
@ -775,10 +775,11 @@ Video
BT.601 or BT.709, a forced, low-quality but correct RGB conversion is
performed. Otherwise, the result will be totally incorrect.
``d3d11va`` is usually safe (if used with ANGLE builds that support
``EGL_KHR_stream path`` - otherwise, it converts to RGB), except that
10 bit input (HEVC main 10 profiles) will be rounded down to 8 bits,
which results in reduced quality.
``d3d11va`` is safe when used with the ``d3d11`` backend. If used with
``angle`` is it usually safe, except that 10 bit input (HEVC main 10
profiles) will be rounded down to 8 bits, which will result in reduced
quality. Also note that with very old ANGLE builds (without
``EGL_KHR_stream path``,) all input will be converted to RGB.
``dxva2`` is not safe. It appears to always use BT.601 for forced RGB
conversion, but actual behavior depends on the GPU drivers. Some drivers
@ -4272,6 +4273,30 @@ The following video options are currently all specific to ``--vo=gpu`` and
as mpv's vulkan implementation currently does not try and protect textures
against concurrent access.
``--d3d11-warp=<yes|no|auto>``
Use WARP (Windows Advanced Rasterization Platform) with the D3D11 GPU
backend (default: auto). This is a high performance software renderer. By
default, it is only used when the system has no hardware adapters that
support D3D11. While the extended GPU features will work with WARP, they
can be very slow.
``--d3d11-feature-level=<12_1|12_0|11_1|11_0|10_1|10_0|9_3|9_2|9_1>``
Select a specific feature level when using the D3D11 GPU backend. By
default, the highest available feature level is used. This option can be
used to select a lower feature level, which is mainly useful for debugging.
Most extended GPU features will not work at 9_x feature levels.
``--d3d11-flip=<yes|no>``
Enable flip-model presentation, which avoids unnecessarily copying the
backbuffer by sharing surfaces with the DWM (default: yes). This may cause
performance issues with older drivers. If flip-model presentation is not
supported (for example, on Windows 7 without the platform update), mpv will
automatically fall back to the older bitblt presentation model.
``--d3d11-sync-interval=<0..4>``
Schedule each frame to be presented for this number of VBlank intervals.
(default: 1) Setting to 1 will enable VSync, setting to 0 will disable it.
``--spirv-compiler=<compiler>``
Controls which compiler is used to translate GLSL to SPIR-V. This is
(currently) only relevant for ``--gpu-api=vulkan``. The possible choices
@ -4694,6 +4719,8 @@ The following video options are currently all specific to ``--vo=gpu`` and
Win32, using WGL for rendering and Direct3D 9Ex for presentation. Works
on Nvidia and AMD. Newer Intel chips with the latest drivers may also
work.
d3d11
Win32, with native Direct3D 11 rendering.
x11
X11/GLX
x11vk
@ -4728,6 +4755,8 @@ The following video options are currently all specific to ``--vo=gpu`` and
Allow only OpenGL (requires OpenGL 2.1+ or GLES 2.0+)
vulkan
Allow only Vulkan (requires a valid/working ``--spirv-compiler``)
d3d11
Allow only ``--gpu-context=d3d11``
``--opengl-es=<mode>``
Controls which type of OpenGL context will be accepted:

View File

@ -90,6 +90,7 @@ extern const struct m_obj_list ao_obj_list;
extern const struct m_sub_options opengl_conf;
extern const struct m_sub_options vulkan_conf;
extern const struct m_sub_options spirv_conf;
extern const struct m_sub_options d3d11_conf;
extern const struct m_sub_options angle_conf;
extern const struct m_sub_options cocoa_conf;
@ -699,6 +700,10 @@ const m_option_t mp_opts[] = {
OPT_SUBSTRUCT("", vulkan_opts, vulkan_conf, 0),
#endif
#if HAVE_D3D11
OPT_SUBSTRUCT("", d3d11_opts, d3d11_conf, 0),
#endif
#if HAVE_EGL_ANGLE_WIN32
OPT_SUBSTRUCT("", angle_opts, angle_conf, 0),
#endif

View File

@ -332,6 +332,7 @@ typedef struct MPOpts {
struct opengl_opts *opengl_opts;
struct vulkan_opts *vulkan_opts;
struct spirv_opts *spirv_opts;
struct d3d11_opts *d3d11_opts;
struct cocoa_opts *cocoa_opts;
struct dvd_opts *dvd_opts;

235
video/out/d3d11/context.c Normal file
View File

@ -0,0 +1,235 @@
/*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* mpv is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include "common/msg.h"
#include "options/m_config.h"
#include "osdep/windows_utils.h"
#include "video/out/gpu/context.h"
#include "video/out/gpu/d3d11_helpers.h"
#include "video/out/gpu/spirv.h"
#include "video/out/w32_common.h"
#include "ra_d3d11.h"
struct d3d11_opts {
int feature_level;
int warp;
int flip;
int sync_interval;
};
#define OPT_BASE_STRUCT struct d3d11_opts
const struct m_sub_options d3d11_conf = {
.opts = (const struct m_option[]) {
OPT_CHOICE("d3d11-warp", warp, 0,
({"auto", -1},
{"no", 0},
{"yes", 1})),
OPT_CHOICE("d3d11-feature-level", feature_level, 0,
({"12_1", D3D_FEATURE_LEVEL_12_1},
{"12_0", D3D_FEATURE_LEVEL_12_0},
{"11_1", D3D_FEATURE_LEVEL_11_1},
{"11_0", D3D_FEATURE_LEVEL_11_0},
{"10_1", D3D_FEATURE_LEVEL_10_1},
{"10_0", D3D_FEATURE_LEVEL_10_0},
{"9_3", D3D_FEATURE_LEVEL_9_3},
{"9_2", D3D_FEATURE_LEVEL_9_2},
{"9_1", D3D_FEATURE_LEVEL_9_1})),
OPT_FLAG("d3d11-flip", flip, 0),
OPT_INTRANGE("d3d11-sync-interval", sync_interval, 0, 0, 4),
{0}
},
.defaults = &(const struct d3d11_opts) {
.feature_level = D3D_FEATURE_LEVEL_12_1,
.warp = -1,
.flip = 1,
.sync_interval = 1,
},
.size = sizeof(struct d3d11_opts)
};
struct priv {
struct d3d11_opts *opts;
struct ra_tex *backbuffer;
ID3D11Device *device;
IDXGISwapChain *swapchain;
};
static struct ra_tex *get_backbuffer(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
ID3D11Texture2D *backbuffer = NULL;
struct ra_tex *tex = NULL;
HRESULT hr;
hr = IDXGISwapChain_GetBuffer(p->swapchain, 0, &IID_ID3D11Texture2D,
(void**)&backbuffer);
if (FAILED(hr)) {
MP_ERR(ctx, "Couldn't get swapchain image\n");
goto done;
}
tex = ra_d3d11_wrap_tex(ctx->ra, (ID3D11Resource *)backbuffer);
done:
SAFE_RELEASE(backbuffer);
return tex;
}
static bool resize(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
HRESULT hr;
ra_tex_free(ctx->ra, &p->backbuffer);
hr = IDXGISwapChain_ResizeBuffers(p->swapchain, 0, ctx->vo->dwidth,
ctx->vo->dheight, DXGI_FORMAT_UNKNOWN, 0);
if (FAILED(hr)) {
MP_FATAL(ctx, "Couldn't resize swapchain: %s\n", mp_HRESULT_to_str(hr));
return false;
}
p->backbuffer = get_backbuffer(ctx);
return true;
}
static bool d3d11_reconfig(struct ra_ctx *ctx)
{
vo_w32_config(ctx->vo);
return resize(ctx);
}
static int d3d11_color_depth(struct ra_swapchain *sw)
{
return 8;
}
static bool d3d11_start_frame(struct ra_swapchain *sw, struct ra_fbo *out_fbo)
{
struct priv *p = sw->priv;
*out_fbo = (struct ra_fbo) {
.tex = p->backbuffer,
.flip = false,
};
return true;
}
static bool d3d11_submit_frame(struct ra_swapchain *sw,
const struct vo_frame *frame)
{
ra_d3d11_flush(sw->ctx->ra);
return true;
}
static void d3d11_swap_buffers(struct ra_swapchain *sw)
{
struct priv *p = sw->priv;
IDXGISwapChain_Present(p->swapchain, p->opts->sync_interval, 0);
}
static int d3d11_control(struct ra_ctx *ctx, int *events, int request, void *arg)
{
int ret = vo_w32_control(ctx->vo, events, request, arg);
if (*events & VO_EVENT_RESIZE) {
if (!resize(ctx))
return VO_ERROR;
}
return ret;
}
static void d3d11_uninit(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
ra_tex_free(ctx->ra, &p->backbuffer);
SAFE_RELEASE(p->swapchain);
vo_w32_uninit(ctx->vo);
SAFE_RELEASE(p->device);
// Destory the RA last to prevent objects we hold from showing up in D3D's
// leak checker
ctx->ra->fns->destroy(ctx->ra);
}
static const struct ra_swapchain_fns d3d11_swapchain = {
.color_depth = d3d11_color_depth,
.start_frame = d3d11_start_frame,
.submit_frame = d3d11_submit_frame,
.swap_buffers = d3d11_swap_buffers,
};
static bool d3d11_init(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv = talloc_zero(ctx, struct priv);
p->opts = mp_get_config_group(ctx, ctx->global, &d3d11_conf);
struct ra_swapchain *sw = ctx->swapchain = talloc_zero(ctx, struct ra_swapchain);
sw->priv = p;
sw->ctx = ctx;
sw->fns = &d3d11_swapchain;
struct d3d11_device_opts dopts = {
.debug = ctx->opts.debug,
.allow_warp = p->opts->warp != 0,
.force_warp = p->opts->warp == 1,
.max_feature_level = p->opts->feature_level,
.max_frame_latency = ctx->opts.swapchain_depth,
};
if (!mp_d3d11_create_present_device(ctx->log, &dopts, &p->device))
goto error;
if (!spirv_compiler_init(ctx))
goto error;
ctx->ra = ra_d3d11_create(p->device, ctx->log, ctx->spirv);
if (!ctx->ra)
goto error;
if (!vo_w32_init(ctx->vo))
goto error;
struct d3d11_swapchain_opts scopts = {
.window = vo_w32_hwnd(ctx->vo),
.width = ctx->vo->dwidth,
.height = ctx->vo->dheight,
.flip = p->opts->flip,
// Add one frame for the backbuffer and one frame of "slack" to reduce
// contention with the window manager when acquiring the backbuffer
.length = ctx->opts.swapchain_depth + 2,
.usage = DXGI_USAGE_RENDER_TARGET_OUTPUT,
};
if (!mp_d3d11_create_swapchain(p->device, ctx->log, &scopts, &p->swapchain))
goto error;
p->backbuffer = get_backbuffer(ctx);
return true;
error:
d3d11_uninit(ctx);
return false;
}
const struct ra_ctx_fns ra_ctx_d3d11 = {
.type = "d3d11",
.name = "d3d11",
.reconfig = d3d11_reconfig,
.control = d3d11_control,
.init = d3d11_init,
.uninit = d3d11_uninit,
};

View File

@ -0,0 +1,195 @@
/*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* mpv is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <windows.h>
#include <d3d11.h>
#include <d3d11_1.h>
#include "config.h"
#include "common/common.h"
#include "osdep/windows_utils.h"
#include "video/hwdec.h"
#include "video/decode/d3d.h"
#include "video/out/d3d11/ra_d3d11.h"
#include "video/out/gpu/hwdec.h"
struct priv_owner {
struct mp_hwdec_ctx hwctx;
ID3D11Device *device;
ID3D11Device1 *device1;
};
struct priv {
ID3D11DeviceContext1 *ctx;
ID3D11Texture2D *copy_tex;
};
static void uninit(struct ra_hwdec *hw)
{
struct priv_owner *p = hw->priv;
if (p->hwctx.ctx)
hwdec_devices_remove(hw->devs, &p->hwctx);
SAFE_RELEASE(p->device);
SAFE_RELEASE(p->device1);
}
static int init(struct ra_hwdec *hw)
{
struct priv_owner *p = hw->priv;
HRESULT hr;
if (!ra_is_d3d11(hw->ra))
return -1;
p->device = ra_d3d11_get_device(hw->ra);
if (!p->device)
return -1;
// D3D11VA requires Direct3D 11.1, so this should always succeed
hr = ID3D11Device_QueryInterface(p->device, &IID_ID3D11Device1,
(void**)&p->device1);
if (FAILED(hr)) {
MP_ERR(hw, "Failed to get D3D11.1 interface: %s\n",
mp_HRESULT_to_str(hr));
return -1;
}
ID3D10Multithread *multithread;
hr = ID3D11Device_QueryInterface(p->device, &IID_ID3D10Multithread,
(void **)&multithread);
if (FAILED(hr)) {
MP_ERR(hw, "Failed to get Multithread interface: %s\n",
mp_HRESULT_to_str(hr));
return -1;
}
ID3D10Multithread_SetMultithreadProtected(multithread, TRUE);
ID3D10Multithread_Release(multithread);
p->hwctx = (struct mp_hwdec_ctx){
.type = HWDEC_D3D11VA,
.driver_name = hw->driver->name,
.ctx = p->device,
.av_device_ref = d3d11_wrap_device_ref(p->device),
};
hwdec_devices_add(hw->devs, &p->hwctx);
return 0;
}
static void mapper_uninit(struct ra_hwdec_mapper *mapper)
{
struct priv *p = mapper->priv;
for (int i = 0; i < 4; i++)
ra_tex_free(mapper->ra, &mapper->tex[i]);
SAFE_RELEASE(p->copy_tex);
SAFE_RELEASE(p->ctx);
}
static int mapper_init(struct ra_hwdec_mapper *mapper)
{
struct priv_owner *o = mapper->owner->priv;
struct priv *p = mapper->priv;
HRESULT hr;
mapper->dst_params = mapper->src_params;
mapper->dst_params.imgfmt = mapper->src_params.hw_subfmt;
mapper->dst_params.hw_subfmt = 0;
struct ra_imgfmt_desc desc = {0};
struct mp_image layout = {0};
if (!ra_get_imgfmt_desc(mapper->ra, mapper->dst_params.imgfmt, &desc))
return -1;
mp_image_set_params(&layout, &mapper->dst_params);
DXGI_FORMAT copy_fmt;
switch (mapper->dst_params.imgfmt) {
case IMGFMT_NV12: copy_fmt = DXGI_FORMAT_NV12; break;
case IMGFMT_P010: copy_fmt = DXGI_FORMAT_P010; break;
default: return -1;
}
// We copy decoder images to an intermediate texture. This is slower than
// the zero-copy path, but according to MSDN, decoder textures should not
// be bound to SRVs, so it is technically correct, and it works around some
// driver "bugs" that can happen with the zero-copy path. It also allows
// samplers to work correctly when the decoder image includes padding.
D3D11_TEXTURE2D_DESC copy_desc = {
.Width = mapper->dst_params.w,
.Height = mapper->dst_params.h,
.MipLevels = 1,
.ArraySize = 1,
.SampleDesc.Count = 1,
.Format = copy_fmt,
.BindFlags = D3D11_BIND_SHADER_RESOURCE,
};
hr = ID3D11Device_CreateTexture2D(o->device, &copy_desc, NULL, &p->copy_tex);
if (FAILED(hr)) {
MP_FATAL(mapper, "Could not create shader resource texture\n");
return -1;
}
for (int i = 0; i < desc.num_planes; i++) {
mapper->tex[i] = ra_d3d11_wrap_tex_video(mapper->ra, p->copy_tex,
mp_image_plane_w(&layout, i),
mp_image_plane_h(&layout, i),
desc.planes[i]);
if (!mapper->tex[i]) {
MP_FATAL(mapper, "Could not create RA texture view\n");
return -1;
}
}
ID3D11Device1_GetImmediateContext1(o->device1, &p->ctx);
return 0;
}
static int mapper_map(struct ra_hwdec_mapper *mapper)
{
struct priv *p = mapper->priv;
ID3D11Texture2D *tex = (void *)mapper->src->planes[0];
int subresource = (intptr_t)mapper->src->planes[1];
ID3D11DeviceContext1_CopySubresourceRegion1(p->ctx,
(ID3D11Resource *)p->copy_tex, 0, 0, 0, 0,
(ID3D11Resource *)tex, subresource, (&(D3D11_BOX) {
.left = 0,
.top = 0,
.front = 0,
.right = mapper->dst_params.w,
.bottom = mapper->dst_params.h,
.back = 1,
}), D3D11_COPY_DISCARD);
return 0;
}
const struct ra_hwdec_driver ra_hwdec_d3d11va = {
.name = "d3d11va",
.priv_size = sizeof(struct priv_owner),
.api = HWDEC_D3D11VA,
.imgfmts = {IMGFMT_D3D11VA, IMGFMT_D3D11NV12, 0},
.init = init,
.uninit = uninit,
.mapper = &(const struct ra_hwdec_mapper_driver){
.priv_size = sizeof(struct priv),
.init = mapper_init,
.uninit = mapper_uninit,
.map = mapper_map,
},
};

2235
video/out/d3d11/ra_d3d11.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,34 @@
#pragma once
#include <stdbool.h>
#include <windows.h>
#include <d3d11.h>
#include <dxgi1_2.h>
#include "video/out/gpu/ra.h"
#include "video/out/gpu/spirv.h"
// Create an RA instance from a D3D11 device. This takes a reference to the
// device, which is released when the RA instance is destroyed.
struct ra *ra_d3d11_create(ID3D11Device *device, struct mp_log *log,
struct spirv_compiler *spirv);
// Flush the immediate context of the wrapped D3D11 device
void ra_d3d11_flush(struct ra *ra);
// Create an RA texture from a D3D11 resource. This takes a reference to the
// texture, which is released when the RA texture is destroyed.
struct ra_tex *ra_d3d11_wrap_tex(struct ra *ra, ID3D11Resource *res);
// As above, but for a D3D11VA video resource. The fmt parameter selects which
// plane of a planar format will be mapped when the RA texture is used.
struct ra_tex *ra_d3d11_wrap_tex_video(struct ra *ra, ID3D11Texture2D *res,
int w, int h,
const struct ra_format *fmt);
// Get the underlying D3D11 device from an RA instance. The returned device is
// refcounted and must be released by the caller.
ID3D11Device *ra_d3d11_get_device(struct ra *ra);
// True if the RA instance was created with ra_d3d11_create()
bool ra_is_d3d11(struct ra *ra);

View File

@ -53,7 +53,14 @@ extern const struct ra_ctx_fns ra_ctx_vulkan_wayland;
extern const struct ra_ctx_fns ra_ctx_vulkan_win;
extern const struct ra_ctx_fns ra_ctx_vulkan_xlib;
/* Direct3D 11 */
extern const struct ra_ctx_fns ra_ctx_d3d11;
static const struct ra_ctx_fns *contexts[] = {
#if HAVE_D3D11
&ra_ctx_d3d11,
#endif
// OpenGL contexts:
#if HAVE_ANDROID
&ra_ctx_android,

View File

@ -46,6 +46,8 @@ static int get_feature_levels(int max_fl, int min_fl,
const D3D_FEATURE_LEVEL **out)
{
static const D3D_FEATURE_LEVEL levels[] = {
D3D_FEATURE_LEVEL_12_1,
D3D_FEATURE_LEVEL_12_0,
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
@ -71,7 +73,8 @@ static int get_feature_levels(int max_fl, int min_fl,
}
static HRESULT create_device(struct mp_log *log, bool warp, bool bgra,
int max_fl, int min_fl, ID3D11Device **dev)
bool debug, int max_fl, int min_fl,
ID3D11Device **dev)
{
const D3D_FEATURE_LEVEL *levels;
int levels_len = get_feature_levels(max_fl, min_fl, &levels);
@ -82,7 +85,11 @@ static HRESULT create_device(struct mp_log *log, bool warp, bool bgra,
D3D_DRIVER_TYPE type = warp ? D3D_DRIVER_TYPE_WARP
: D3D_DRIVER_TYPE_HARDWARE;
UINT flags = bgra ? D3D11_CREATE_DEVICE_BGRA_SUPPORT : 0;
UINT flags = 0;
if (bgra)
flags |= D3D11_CREATE_DEVICE_BGRA_SUPPORT;
if (debug)
flags |= D3D11_CREATE_DEVICE_DEBUG;
return pD3D11CreateDevice(NULL, type, NULL, flags, levels, levels_len,
D3D11_SDK_VERSION, dev, NULL, NULL);
}
@ -116,7 +123,7 @@ bool mp_d3d11_create_present_device(struct mp_log *log,
max_fl = max_fl ? max_fl : D3D_FEATURE_LEVEL_11_0;
min_fl = min_fl ? min_fl : D3D_FEATURE_LEVEL_9_1;
hr = create_device(log, warp, bgra, max_fl, min_fl, &dev);
hr = create_device(log, warp, bgra, opts->debug, max_fl, min_fl, &dev);
if (SUCCEEDED(hr))
break;
@ -127,8 +134,19 @@ bool mp_d3d11_create_present_device(struct mp_log *log,
continue;
}
// Trying to create a D3D_FEATURE_LEVEL_12_0 device on Windows 8.1 or
// below will not succeed. Try an 11_1 device.
if (max_fl >= D3D_FEATURE_LEVEL_12_0 &&
min_fl <= D3D_FEATURE_LEVEL_11_1)
{
mp_dbg(log, "Failed to create 12_0+ device, trying 11_1\n");
max_fl = D3D_FEATURE_LEVEL_11_1;
bgra = true;
continue;
}
// Trying to create a D3D_FEATURE_LEVEL_11_1 device on Windows 7
// without the platform update will not succeed. Try a 11_0 device.
// without the platform update will not succeed. Try an 11_0 device.
if (max_fl >= D3D_FEATURE_LEVEL_11_1 &&
min_fl <= D3D_FEATURE_LEVEL_11_0)
{

View File

@ -23,7 +23,13 @@
#include <d3d11.h>
#include <dxgi1_2.h>
#define D3D_FEATURE_LEVEL_12_0 (0xc000)
#define D3D_FEATURE_LEVEL_12_1 (0xc100)
struct d3d11_device_opts {
// Enable the debug layer (D3D11_CREATE_DEVICE_DEBUG)
bool debug;
// Allow a software (WARP) adapter. Note, sometimes a software adapter will
// be used even when allow_warp is false. This is because, on Windows 8 and
// up, if there are no hardware adapters, Windows will pretend the WARP

View File

@ -34,6 +34,7 @@ extern const struct ra_hwdec_driver ra_hwdec_d3d11egl;
extern const struct ra_hwdec_driver ra_hwdec_d3d11eglrgb;
extern const struct ra_hwdec_driver ra_hwdec_dxva2gldx;
extern const struct ra_hwdec_driver ra_hwdec_dxva2;
extern const struct ra_hwdec_driver ra_hwdec_d3d11va;
extern const struct ra_hwdec_driver ra_hwdec_cuda;
extern const struct ra_hwdec_driver ra_hwdec_cuda_nvdec;
extern const struct ra_hwdec_driver ra_hwdec_rpi_overlay;
@ -58,6 +59,9 @@ static const struct ra_hwdec_driver *const mpgl_hwdec_drivers[] = {
#if HAVE_D3D9_HWACCEL
&ra_hwdec_dxva2egl,
#endif
#if HAVE_D3D11
&ra_hwdec_d3d11va,
#endif
#endif
#if HAVE_GL_DXINTEROP_D3D9
&ra_hwdec_dxva2gldx,

View File

@ -24,7 +24,7 @@
#include "angle_dynamic.h"
#include "egl_helpers.h"
#include "d3d11_helpers.h"
#include "video/out/gpu/d3d11_helpers.h"
#include "common/common.h"
#include "options/m_config.h"

17
wscript
View File

@ -753,6 +753,19 @@ video_output_features = [
'desc': 'Direct3D support',
'deps': 'win32-desktop && gpl',
'func': check_cc(header_name='d3d9.h'),
}, {
'name': '--shaderc',
'desc': 'libshaderc SPIR-V compiler',
'func': check_cc(header_name='shaderc/shaderc.h', lib='shaderc_shared'),
}, {
'name': '--crossc',
'desc': 'libcrossc SPIR-V translator',
'func': check_pkg_config('crossc'),
}, {
'name': '--d3d11',
'desc': 'Direct3D 11 video output',
'deps': 'win32-desktop && shaderc && crossc',
'func': check_cc(header_name=['d3d11_1.h', 'dxgi1_2.h']),
}, {
# We need MMAL/bcm_host/dispmanx APIs. Also, most RPI distros require
# every project to hardcode the paths to the include directories. Also,
@ -806,10 +819,6 @@ video_output_features = [
'name': '--vulkan',
'desc': 'Vulkan context support',
'func': check_pkg_config('vulkan'),
}, {
'name': '--shaderc',
'desc': 'libshaderc SPIR-V compiler',
'func': check_cc(header_name='shaderc/shaderc.h', lib='shaderc_shared'),
}, {
'name': 'egl-helpers',
'desc': 'EGL helper functions',

View File

@ -401,8 +401,12 @@ def build(ctx):
( "video/out/cocoa_common.m", "cocoa" ),
( "video/out/dither.c" ),
( "video/out/filter_kernels.c" ),
( "video/out/d3d11/context.c", "d3d11" ),
( "video/out/d3d11/hwdec_d3d11va.c", "d3d11 && d3d-hwaccel" ),
( "video/out/d3d11/ra_d3d11.c", "d3d11" ),
( "video/out/opengl/angle_dynamic.c", "egl-angle" ),
( "video/out/gpu/context.c" ),
( "video/out/gpu/d3d11_helpers.c", "d3d11 || egl-angle-win32" ),
( "video/out/gpu/hwdec.c" ),
( "video/out/gpu/lcms.c" ),
( "video/out/gpu/osd.c" ),
@ -432,7 +436,6 @@ def build(ctx):
( "video/out/opengl/context_glx.c", "gl-x11" ),
( "video/out/opengl/context_x11egl.c", "egl-x11" ),
( "video/out/opengl/cuda_dynamic.c", "cuda-hwaccel" ),
( "video/out/opengl/d3d11_helpers.c", "egl-angle-win32" ),
( "video/out/opengl/egl_helpers.c", "egl-helpers" ),
( "video/out/opengl/hwdec_cuda.c", "cuda-hwaccel" ),
( "video/out/opengl/hwdec_d3d11egl.c", "d3d-hwaccel" ),