diff --git a/Makefile.common b/Makefile.common
index d8f78db89b..b183da5e5f 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -1269,7 +1269,7 @@ endif
ifeq ($(HAVE_D3D12), 1)
OBJ += gfx/drivers/d3d12.o gfx/common/d3d12_common.o \
- gfx/drivers_font/d3d12_font.o
+ gfx/drivers_font/d3d12_font.o menu/drivers_display/menu_display_d3d12.o
DEFINES += -DHAVE_D3D12
endif
diff --git a/Makefile.msvc b/Makefile.msvc
index 7760279670..77d02fc9fa 100644
--- a/Makefile.msvc
+++ b/Makefile.msvc
@@ -55,6 +55,7 @@ HAVE_LANGEXTRA := 1
HAVE_CHEEVOS := 1
HAVE_KEYMAPPER := 1
HAVE_SHADERPIPELINE := 1
+HAVE_IMAGEVIEWER := 1
include Makefile.common
INCLUDE_DIRS := $(patsubst -isystem%,-I%,$(INCLUDE_DIRS))
diff --git a/gfx/common/d3d12_common.h b/gfx/common/d3d12_common.h
index eb320e3ba3..936d50ff77 100644
--- a/gfx/common/d3d12_common.h
+++ b/gfx/common/d3d12_common.h
@@ -1311,7 +1311,27 @@ typedef struct
bool dirty;
} d3d12_texture_t;
-#define TEXTURE_DESC_SLOTS_COUNT 128
+#ifndef ALIGN
+#ifdef _MSC_VER
+#define ALIGN(x) __declspec(align(x))
+#else
+#define ALIGN(x) __attribute__((aligned(x)))
+#endif
+#endif
+
+typedef struct ALIGN(16)
+{
+ math_matrix_4x4 mvp;
+ struct
+ {
+ float width;
+ float height;
+ } OutputSize;
+ float time;
+} d3d12_uniform_t;
+
+static_assert(
+ (!(sizeof(d3d12_uniform_t) & 0xF)), "sizeof(d3d12_uniform_t) must be a multiple of 16");
typedef struct
{
@@ -1386,6 +1406,7 @@ typedef struct
} sprites;
D3D12PipelineState pipes[GFX_MAX_SHADERS];
+ d3d12_uniform_t ubo_values;
D3D12Resource ubo;
D3D12_CONSTANT_BUFFER_VIEW_DESC ubo_view;
DXGI_FORMAT format;
@@ -1395,6 +1416,8 @@ typedef struct
bool resize_chain;
bool keep_aspect;
bool resize_viewport;
+ D3D12Resource menu_pipeline_vbo;
+ D3D12_VERTEX_BUFFER_VIEW menu_pipeline_vbo_view;
#ifdef DEBUG
D3D12Debug debugController;
diff --git a/gfx/drivers/d3d12.c b/gfx/drivers/d3d12.c
index 87f866747c..3798c29890 100644
--- a/gfx/drivers/d3d12.c
+++ b/gfx/drivers/d3d12.c
@@ -26,11 +26,13 @@
#include "../common/d3d12_common.h"
#include "../common/d3dcompiler_common.h"
-//#include "../../menu/menu_driver.h"
+#include "../../menu/menu_driver.h"
#include "../../driver.h"
#include "../../verbosity.h"
#include "../../configuration.h"
+#include "wiiu/wiiu_dbg.h"
+
static void d3d12_set_filtering(void* data, unsigned index, bool smooth)
{
int i;
@@ -71,10 +73,10 @@ static void d3d12_update_viewport(void* data, bool force_full)
video_driver_update_viewport(&d3d12->vp, force_full, d3d12->keep_aspect);
- d3d12->frame.viewport.TopLeftX = (float)d3d12->vp.x;
- d3d12->frame.viewport.TopLeftY = (float)d3d12->vp.y;
- d3d12->frame.viewport.Width = (float)d3d12->vp.width;
- d3d12->frame.viewport.Height = (float)d3d12->vp.height;
+ d3d12->frame.viewport.TopLeftX = d3d12->vp.x;
+ d3d12->frame.viewport.TopLeftY = d3d12->vp.y;
+ d3d12->frame.viewport.Width = d3d12->vp.width;
+ d3d12->frame.viewport.Height = d3d12->vp.height;
d3d12->frame.viewport.MaxDepth = 0.0f;
d3d12->frame.viewport.MaxDepth = 1.0f;
@@ -160,6 +162,7 @@ static bool d3d12_gfx_init_pipelines(d3d12_video_t* d3d12)
if (!d3d_compile(shader, sizeof(shader), NULL, "GSMain", "gs_5_0", &gs_code))
goto error;
+ // desc.BlendState.RenderTarget[0].BlendEnable = false;
desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
desc.InputLayout.pInputElementDescs = inputElementDesc;
desc.InputLayout.NumElements = countof(inputElementDesc);
@@ -301,9 +304,9 @@ static bool d3d12_gfx_init_pipelines(d3d12_video_t* d3d12)
vs_code = NULL;
ps_code = NULL;
- if (!d3d_compile(ribbon_simple, sizeof(ribbon), NULL, "VSMain", "vs_5_0", &vs_code))
+ if (!d3d_compile(ribbon_simple, sizeof(ribbon_simple), NULL, "VSMain", "vs_5_0", &vs_code))
goto error;
- if (!d3d_compile(ribbon_simple, sizeof(ribbon), NULL, "PSMain", "ps_5_0", &ps_code))
+ if (!d3d_compile(ribbon_simple, sizeof(ribbon_simple), NULL, "PSMain", "ps_5_0", &ps_code))
goto error;
if (!d3d12_init_pipeline(
@@ -383,6 +386,8 @@ static void*
d3d12_gfx_init(const video_info_t* video, const input_driver_t** input, void** input_data)
{
WNDCLASSEX wndclass = { 0 };
+ MONITORINFOEX current_mon;
+ HMONITOR hm_to_use;
settings_t* settings = config_get_ptr();
d3d12_video_t* d3d12 = (d3d12_video_t*)calloc(1, sizeof(*d3d12));
@@ -394,7 +399,17 @@ d3d12_gfx_init(const video_info_t* video, const input_driver_t** input, void** i
wndclass.lpfnWndProc = WndProcD3D;
win32_window_init(&wndclass, true, NULL);
- if (!win32_set_video_mode(d3d12, video->width, video->height, video->fullscreen))
+ win32_monitor_info(¤t_mon, &hm_to_use, &d3d12->cur_mon_id);
+
+ d3d12->vp.full_width = video->width;
+ d3d12->vp.full_height = video->height;
+
+ if (!d3d12->vp.full_width)
+ d3d12->vp.full_width = current_mon.rcMonitor.right - current_mon.rcMonitor.left;
+ if (!d3d12->vp.full_height)
+ d3d12->vp.full_height = current_mon.rcMonitor.bottom - current_mon.rcMonitor.top;
+
+ if (!win32_set_video_mode(d3d12, d3d12->vp.full_width, d3d12->vp.full_height, video->fullscreen))
{
RARCH_ERR("[D3D12]: win32_set_video_mode failed.\n");
goto error;
@@ -414,7 +429,7 @@ d3d12_gfx_init(const video_info_t* video, const input_driver_t** input, void** i
if (!d3d12_init_queue(d3d12))
goto error;
- if (!d3d12_init_swapchain(d3d12, video->width, video->height, main_window.hwnd))
+ if (!d3d12_init_swapchain(d3d12, d3d12->vp.full_width, d3d12->vp.full_height, main_window.hwnd))
goto error;
d3d12_init_samplers(d3d12);
@@ -429,21 +444,20 @@ d3d12_gfx_init(const video_info_t* video, const input_driver_t** input, void** i
d3d12->sprites.vbo_view.BufferLocation = d3d12_create_buffer(
d3d12->device, d3d12->sprites.vbo_view.SizeInBytes, &d3d12->sprites.vbo);
- d3d12->keep_aspect = video->force_aspect;
- d3d12->chain.vsync = video->vsync;
- d3d12->format = video->rgb32 ? DXGI_FORMAT_B8G8R8X8_UNORM : DXGI_FORMAT_B5G6R5_UNORM;
- d3d12->frame.texture.desc.Format = d3d12->format;
-
- d3d12->ubo_view.SizeInBytes = sizeof(math_matrix_4x4);
+ d3d12->ubo_view.SizeInBytes = sizeof(d3d12_uniform_t);
d3d12->ubo_view.BufferLocation =
d3d12_create_buffer(d3d12->device, d3d12->ubo_view.SizeInBytes, &d3d12->ubo);
- d3d12->frame.ubo_view.SizeInBytes = sizeof(math_matrix_4x4);
+ d3d12->frame.ubo_view.SizeInBytes = sizeof(d3d12_uniform_t);
d3d12->frame.ubo_view.BufferLocation =
d3d12_create_buffer(d3d12->device, d3d12->frame.ubo_view.SizeInBytes, &d3d12->frame.ubo);
matrix_4x4_ortho(d3d12->mvp_no_rot, 0.0f, 1.0f, 0.0f, 1.0f, -1.0f, 1.0f);
+ d3d12->ubo_values.mvp = d3d12->mvp_no_rot;
+ d3d12->ubo_values.OutputSize.width = d3d12->chain.viewport.Width;
+ d3d12->ubo_values.OutputSize.height = d3d12->chain.viewport.Height;
+
{
math_matrix_4x4* mvp;
D3D12_RANGE read_range = { 0, 0 };
@@ -453,9 +467,14 @@ d3d12_gfx_init(const video_info_t* video, const input_driver_t** input, void** i
}
d3d12_gfx_set_rotation(d3d12, 0);
- d3d12->vp.full_width = video->width;
- d3d12->vp.full_height = video->height;
- d3d12->resize_viewport = true;
+ video_driver_set_size(&d3d12->vp.full_width, &d3d12->vp.full_height);
+ d3d12->chain.viewport.Width = d3d12->vp.full_width;
+ d3d12->chain.viewport.Height = d3d12->vp.full_height;
+ d3d12->resize_viewport = true;
+ d3d12->keep_aspect = video->force_aspect;
+ d3d12->chain.vsync = video->vsync;
+ d3d12->format = video->rgb32 ? DXGI_FORMAT_B8G8R8X8_UNORM : DXGI_FORMAT_B5G6R5_UNORM;
+ d3d12->frame.texture.desc.Format = d3d12->format;
font_driver_init_osd(d3d12, false, video->is_threaded, FONT_DRIVER_RENDER_D3D12_API);
@@ -496,8 +515,18 @@ static bool d3d12_gfx_frame(
}
d3d12->chain.frame_index = DXGIGetCurrentBackBufferIndex(d3d12->chain.handle);
- d3d12->resize_chain = false;
- d3d12->resize_viewport = true;
+
+ d3d12->chain.viewport.Width = video_info->width;
+ d3d12->chain.viewport.Height = video_info->height;
+ d3d12->chain.scissorRect.right = video_info->width;
+ d3d12->chain.scissorRect.bottom = video_info->height;
+ d3d12->resize_chain = false;
+ d3d12->resize_viewport = true;
+
+ d3d12->ubo_values.OutputSize.width = d3d12->chain.viewport.Width;
+ d3d12->ubo_values.OutputSize.height = d3d12->chain.viewport.Height;
+
+ video_driver_set_size(&video_info->width, &video_info->height);
}
PERF_START();
@@ -578,7 +607,7 @@ static bool d3d12_gfx_frame(
D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1, &d3d12->sprites.vbo_view);
d3d12->sprites.enabled = true;
-#if 0
+#if 1
if (d3d12->menu.enabled)
menu_driver_frame(video_info);
#endif
@@ -589,7 +618,6 @@ static bool d3d12_gfx_frame(
}
d3d12->sprites.enabled = false;
-
d3d12_resource_transition(
d3d12->queue.cmd, d3d12->chain.renderTargets[d3d12->chain.frame_index],
D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT);
@@ -759,11 +787,64 @@ static void d3d12_gfx_set_osd_msg(
}
}
+static uintptr_t d3d12_gfx_load_texture(
+ void* video_data, void* data, bool threaded, enum texture_filter_type filter_type)
+{
+ d3d12_texture_t* texture = NULL;
+ d3d12_video_t* d3d12 = (d3d12_video_t*)video_data;
+ struct texture_image* image = (struct texture_image*)data;
+
+ if (!d3d12)
+ return 0;
+
+ texture = (d3d12_texture_t*)calloc(1, sizeof(*texture));
+
+ if (!texture)
+ return 0;
+
+ /* todo : mipmapping */
+ switch (filter_type)
+ {
+ case TEXTURE_FILTER_MIPMAP_LINEAR:
+ /* fallthrough */
+ case TEXTURE_FILTER_LINEAR:
+ texture->sampler = d3d12->samplers[RARCH_FILTER_LINEAR][RARCH_WRAP_DEFAULT];
+ break;
+ case TEXTURE_FILTER_MIPMAP_NEAREST:
+ /* fallthrough */
+ case TEXTURE_FILTER_NEAREST:
+ texture->sampler = d3d12->samplers[RARCH_FILTER_NEAREST][RARCH_WRAP_DEFAULT];
+ break;
+ }
+
+ texture->desc.Width = image->width;
+ texture->desc.Height = image->height;
+ texture->desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
+ texture->srv_heap = &d3d12->desc.srv_heap;
+
+ d3d12_init_texture(d3d12->device, texture);
+
+ d3d12_update_texture(
+ image->width, image->height, 0, DXGI_FORMAT_B8G8R8A8_UNORM, image->pixels, texture);
+
+ return (uintptr_t)texture;
+}
+static void d3d12_gfx_unload_texture(void* data, uintptr_t handle)
+{
+ d3d12_texture_t* texture = (d3d12_texture_t*)handle;
+
+ if (!texture)
+ return;
+
+ d3d12_release_texture(texture);
+ free(texture);
+}
+
static const video_poke_interface_t d3d12_poke_interface = {
NULL, /* set_coords */
NULL, /* set_mvp */
- NULL, /* load_texture */
- NULL, /* unload_texture */
+ d3d12_gfx_load_texture,
+ d3d12_gfx_unload_texture,
NULL, /* set_video_mode */
d3d12_set_filtering,
NULL, /* get_video_output_size */
diff --git a/griffin/griffin.c b/griffin/griffin.c
index 30d21c4f35..602764cf15 100644
--- a/griffin/griffin.c
+++ b/griffin/griffin.c
@@ -1172,6 +1172,10 @@ MENU
#include "../menu/drivers_display/menu_display_d3d11.c"
#endif
+#if defined(HAVE_D3D12)
+#include "../menu/drivers_display/menu_display_d3d12.c"
+#endif
+
#ifdef HAVE_OPENGL
#include "../menu/drivers_display/menu_display_gl.c"
#endif
diff --git a/menu/drivers_display/menu_display_d3d12.c b/menu/drivers_display/menu_display_d3d12.c
new file mode 100644
index 0000000000..122ad20c4a
--- /dev/null
+++ b/menu/drivers_display/menu_display_d3d12.c
@@ -0,0 +1,244 @@
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2014-2018 - Ali Bouhlel
+ *
+ * RetroArch is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * RetroArch 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with RetroArch.
+ * If not, see .
+ */
+
+#define CINTERFACE
+
+#include
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "../menu_driver.h"
+
+#include "../../retroarch.h"
+#include "../../gfx/font_driver.h"
+#include "../../gfx/video_driver.h"
+#include "../../gfx/common/d3d12_common.h"
+
+static const float* menu_display_d3d12_get_default_vertices(void) { return NULL; }
+
+static const float* menu_display_d3d12_get_default_tex_coords(void) { return NULL; }
+
+static void* menu_display_d3d12_get_default_mvp(void) { return NULL; }
+
+static void menu_display_d3d12_blend_begin(void)
+{
+ d3d12_video_t* d3d12 = (d3d12_video_t*)video_driver_get_ptr(false);
+
+ /*todo: d3d12->sprites.pipe_blend */
+ D3D12SetPipelineState(d3d12->queue.cmd, d3d12->sprites.pipe);
+}
+
+static void menu_display_d3d12_blend_end(void)
+{
+ d3d12_video_t* d3d12 = (d3d12_video_t*)video_driver_get_ptr(false);
+
+ /*todo: d3d12->sprites.pipe_noblend */
+ D3D12SetPipelineState(d3d12->queue.cmd, d3d12->sprites.pipe);
+}
+
+static void menu_display_d3d12_viewport(void* data) {}
+
+static void menu_display_d3d12_draw(void* data)
+{
+ d3d12_video_t* d3d12 = (d3d12_video_t*)video_driver_get_ptr(false);
+ menu_display_ctx_draw_t* draw = (menu_display_ctx_draw_t*)data;
+
+ if (!d3d12 || !draw || !draw->texture)
+ return;
+
+ switch (draw->pipeline.id)
+ {
+ case VIDEO_SHADER_MENU:
+ case VIDEO_SHADER_MENU_2:
+ case VIDEO_SHADER_MENU_3:
+ case VIDEO_SHADER_MENU_4:
+ case VIDEO_SHADER_MENU_5:
+ case VIDEO_SHADER_MENU_6:
+ D3D12SetPipelineState(d3d12->queue.cmd, d3d12->pipes[draw->pipeline.id]);
+ D3D12DrawInstanced(d3d12->queue.cmd, draw->coords->vertices, 1, 0, 0);
+ D3D12SetPipelineState(d3d12->queue.cmd, d3d12->sprites.pipe);
+ D3D12IASetPrimitiveTopology(d3d12->queue.cmd, D3D_PRIMITIVE_TOPOLOGY_POINTLIST);
+ D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1, &d3d12->sprites.vbo_view);
+ return;
+ }
+
+ if (!d3d12->sprites.enabled)
+ return;
+
+ if (d3d12->sprites.offset + 1 > d3d12->sprites.capacity)
+ d3d12->sprites.offset = 0;
+
+ {
+ d3d12_sprite_t* v;
+ D3D12_RANGE range = { 0, 0 };
+ D3D12Map(d3d12->sprites.vbo, 0, &range, (void**)&v);
+ v += d3d12->sprites.offset;
+
+ v->pos.x = draw->x / (float)d3d12->chain.viewport.Width;
+ v->pos.y = (d3d12->chain.viewport.Height - draw->y - draw->height) /
+ (float)d3d12->chain.viewport.Height;
+ v->pos.w = draw->width / (float)d3d12->chain.viewport.Width;
+ v->pos.h = draw->height / (float)d3d12->chain.viewport.Height;
+
+ v->coords.u = 0.0f;
+ v->coords.v = 0.0f;
+ v->coords.w = 1.0f;
+ v->coords.h = 1.0f;
+
+ if (draw->scale_factor)
+ v->params.scaling = draw->scale_factor;
+ else
+ v->params.scaling = 1.0f;
+
+ v->params.rotation = draw->rotation;
+
+ v->colors[3] = DXGI_COLOR_RGBA(
+ 0xFF * draw->coords->color[0], 0xFF * draw->coords->color[1],
+ 0xFF * draw->coords->color[2], 0xFF * draw->coords->color[3]);
+ v->colors[2] = DXGI_COLOR_RGBA(
+ 0xFF * draw->coords->color[4], 0xFF * draw->coords->color[5],
+ 0xFF * draw->coords->color[6], 0xFF * draw->coords->color[7]);
+ v->colors[1] = DXGI_COLOR_RGBA(
+ 0xFF * draw->coords->color[8], 0xFF * draw->coords->color[9],
+ 0xFF * draw->coords->color[10], 0xFF * draw->coords->color[12]);
+ v->colors[0] = DXGI_COLOR_RGBA(
+ 0xFF * draw->coords->color[12], 0xFF * draw->coords->color[13],
+ 0xFF * draw->coords->color[14], 0xFF * draw->coords->color[15]);
+
+ range.Begin = d3d12->sprites.offset * sizeof(*v);
+ range.End = (d3d12->sprites.offset + 1) * sizeof(*v);
+ D3D12Unmap(d3d12->sprites.vbo, 0, &range);
+ }
+
+ {
+ d3d12_texture_t* texture = (d3d12_texture_t*)draw->texture;
+ if (texture->dirty)
+ d3d12_upload_texture(d3d12->queue.cmd, texture);
+ d3d12_set_texture_and_sampler(d3d12->queue.cmd, texture);
+ }
+
+ D3D12DrawInstanced(d3d12->queue.cmd, 1, 1, d3d12->sprites.offset, 0);
+ d3d12->sprites.offset++;
+ return;
+}
+
+static void menu_display_d3d12_draw_pipeline(void* data)
+{
+ menu_display_ctx_draw_t* draw = (menu_display_ctx_draw_t*)data;
+ d3d12_video_t* d3d12 = (d3d12_video_t*)video_driver_get_ptr(false);
+
+ if (!d3d12 || !draw)
+ return;
+
+ switch (draw->pipeline.id)
+ {
+ case VIDEO_SHADER_MENU:
+ case VIDEO_SHADER_MENU_2:
+ {
+ video_coord_array_t* ca = menu_display_get_coords_array();
+
+ if (!d3d12->menu_pipeline_vbo)
+ {
+ void* vertex_data_begin;
+ D3D12_RANGE read_range = { 0, 0 };
+
+ d3d12->menu_pipeline_vbo_view.StrideInBytes = 2 * sizeof(float);
+ d3d12->menu_pipeline_vbo_view.SizeInBytes =
+ ca->coords.vertices * d3d12->menu_pipeline_vbo_view.StrideInBytes;
+ d3d12->menu_pipeline_vbo_view.BufferLocation = d3d12_create_buffer(
+ d3d12->device, d3d12->menu_pipeline_vbo_view.SizeInBytes,
+ &d3d12->menu_pipeline_vbo);
+
+ D3D12Map(d3d12->menu_pipeline_vbo, 0, &read_range, &vertex_data_begin);
+ memcpy(vertex_data_begin, ca->coords.vertex, d3d12->menu_pipeline_vbo_view.SizeInBytes);
+ D3D12Unmap(d3d12->menu_pipeline_vbo, 0, NULL);
+ }
+ D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1, &d3d12->menu_pipeline_vbo_view);
+ draw->coords->vertices = ca->coords.vertices;
+ break;
+ }
+
+ case VIDEO_SHADER_MENU_3:
+ case VIDEO_SHADER_MENU_4:
+ case VIDEO_SHADER_MENU_5:
+ case VIDEO_SHADER_MENU_6:
+ D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1, &d3d12->frame.vbo_view);
+ draw->coords->vertices = 4;
+ break;
+ default:
+ return;
+ }
+ D3D12IASetPrimitiveTopology(d3d12->queue.cmd, D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
+
+ d3d12->ubo_values.time += 0.01f;
+
+ {
+ D3D12_RANGE read_range = { 0, 0 };
+ d3d12_uniform_t* mapped_ubo;
+ D3D12Map(d3d12->ubo, 0, &read_range, (void**)&mapped_ubo);
+ *mapped_ubo = d3d12->ubo_values;
+ D3D12Unmap(d3d12->ubo, 0, NULL);
+ }
+ D3D12SetGraphicsRootConstantBufferView(
+ d3d12->queue.cmd, ROOT_ID_UBO, d3d12->ubo_view.BufferLocation);
+}
+
+static void menu_display_d3d12_restore_clear_color(void) {}
+
+static void menu_display_d3d12_clear_color(menu_display_ctx_clearcolor_t* clearcolor)
+{
+ d3d12_video_t* d3d12 = (d3d12_video_t*)video_driver_get_ptr(false);
+
+ if (!d3d12 || !clearcolor)
+ return;
+
+ D3D12ClearRenderTargetView(
+ d3d12->queue.cmd, d3d12->chain.desc_handles[d3d12->chain.frame_index], (float*)clearcolor,
+ 0, NULL);
+}
+
+static bool menu_display_d3d12_font_init_first(
+ void** font_handle,
+ void* video_data,
+ const char* font_path,
+ float font_size,
+ bool is_threaded)
+{
+ font_data_t** handle = (font_data_t**)font_handle;
+ font_data_t* new_handle = font_driver_init_first(
+ video_data, font_path, font_size, true, is_threaded, FONT_DRIVER_RENDER_D3D12_API);
+ if (!new_handle)
+ return false;
+ *handle = new_handle;
+ return true;
+}
+
+menu_display_ctx_driver_t menu_display_ctx_d3d12 = {
+ menu_display_d3d12_draw,
+ menu_display_d3d12_draw_pipeline,
+ menu_display_d3d12_viewport,
+ menu_display_d3d12_blend_begin,
+ menu_display_d3d12_blend_end,
+ menu_display_d3d12_restore_clear_color,
+ menu_display_d3d12_clear_color,
+ menu_display_d3d12_get_default_mvp,
+ menu_display_d3d12_get_default_vertices,
+ menu_display_d3d12_get_default_tex_coords,
+ menu_display_d3d12_font_init_first,
+ MENU_VIDEO_DRIVER_DIRECT3D12,
+ "menu_display_d3d12",
+};
diff --git a/menu/menu_driver.c b/menu/menu_driver.c
index 787252526e..9675d2ecc5 100644
--- a/menu/menu_driver.c
+++ b/menu/menu_driver.c
@@ -93,6 +93,9 @@ static menu_display_ctx_driver_t *menu_display_ctx_drivers[] = {
#ifdef HAVE_D3D11
&menu_display_ctx_d3d11,
#endif
+#ifdef HAVE_D3D12
+ &menu_display_ctx_d3d12,
+#endif
#ifdef HAVE_OPENGL
&menu_display_ctx_gl,
#endif
@@ -229,6 +232,10 @@ static bool menu_display_check_compatibility(
if (string_is_equal(video_driver, "d3d11"))
return true;
break;
+ case MENU_VIDEO_DRIVER_DIRECT3D12:
+ if (string_is_equal(video_driver, "d3d12"))
+ return true;
+ break;
case MENU_VIDEO_DRIVER_VITA2D:
if (string_is_equal(video_driver, "vita2d"))
return true;
diff --git a/menu/menu_driver.h b/menu/menu_driver.h
index 33a6a551f3..9c2f9cf14c 100644
--- a/menu/menu_driver.h
+++ b/menu/menu_driver.h
@@ -280,6 +280,7 @@ enum menu_display_driver_type
MENU_VIDEO_DRIVER_VULKAN,
MENU_VIDEO_DRIVER_DIRECT3D,
MENU_VIDEO_DRIVER_DIRECT3D11,
+ MENU_VIDEO_DRIVER_DIRECT3D12,
MENU_VIDEO_DRIVER_VITA2D,
MENU_VIDEO_DRIVER_CTR,
MENU_VIDEO_DRIVER_WIIU,
@@ -735,6 +736,7 @@ extern menu_display_ctx_driver_t menu_display_ctx_gl;
extern menu_display_ctx_driver_t menu_display_ctx_vulkan;
extern menu_display_ctx_driver_t menu_display_ctx_d3d;
extern menu_display_ctx_driver_t menu_display_ctx_d3d11;
+extern menu_display_ctx_driver_t menu_display_ctx_d3d12;
extern menu_display_ctx_driver_t menu_display_ctx_vita2d;
extern menu_display_ctx_driver_t menu_display_ctx_ctr;
extern menu_display_ctx_driver_t menu_display_ctx_wiiu;