add D3D12 HW_render support. (#15177)

This commit is contained in:
aliaspider 2023-04-10 01:08:44 +01:00 committed by GitHub
parent 4350ec24be
commit 0adbd6905f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 139 additions and 10 deletions

View File

@ -25,6 +25,8 @@
#include "dxgi_common.h"
#include <d3d12.h>
#include <libretro_d3d.h>
#include "../common/d3dcompiler_common.h"
#include "../drivers_shader/slang_process.h"
@ -166,7 +168,8 @@ enum d3d12_video_flags
D3D12_ST_FLAG_HDR_ENABLE = (1 << 11),
D3D12_ST_FLAG_VSYNC = (1 << 12),
D3D12_ST_FLAG_WAITABLE_SWAPCHAINS = (1 << 13),
D3D12_ST_FLAG_WAIT_FOR_VBLANK = (1 << 14)
D3D12_ST_FLAG_WAIT_FOR_VBLANK = (1 << 14),
D3D12_ST_FLAG_HW_IFACE_ENABLE = (1 << 15)
};
typedef struct
@ -188,6 +191,10 @@ typedef struct
#endif /* DEBUG */
#endif /* DEVICE_DEBUG */
struct retro_hw_render_interface_d3d12 hw_iface;
D3D12Resource hw_render_texture;
DXGI_FORMAT hw_render_texture_format;
IDXGIAdapter1 *adapters[D3D12_MAX_GPU_COUNT];
struct string_list *gpu_list;

View File

@ -887,7 +887,7 @@ static bool d3d12_gfx_init_pipelines(d3d12_video_t* d3d12)
}
#endif
desc.BlendState.RenderTarget[0] = d3d12_blend_enable_desc;
desc.BlendState.RenderTarget[0] = d3d12_blend_disable_desc;
desc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
{
@ -1738,7 +1738,7 @@ static void d3d12_init_queue(d3d12_video_t* d3d12)
{
static const D3D12_COMMAND_QUEUE_DESC desc = {
D3D12_COMMAND_LIST_TYPE_DIRECT,
0,
D3D12_COMMAND_QUEUE_PRIORITY_NORMAL,
D3D12_COMMAND_QUEUE_FLAG_NONE,
0
};
@ -1793,6 +1793,13 @@ static void d3d12_create_fullscreen_quad_vbo(
D3D12Unmap(*vbo, 0, NULL);
}
static void d3d12_set_hw_render_texture(void* data, ID3D12Resource* texture, DXGI_FORMAT format)
{
d3d12_video_t* d3d12 = (d3d12_video_t*)data;
d3d12->hw_render_texture = texture;
d3d12->hw_render_texture_format = format;
}
static void *d3d12_gfx_init(const video_info_t* video,
input_driver_t** input, void** input_data)
{
@ -1982,6 +1989,20 @@ static void *d3d12_gfx_init(const video_info_t* video,
d3d12_gfx_set_shader(d3d12, type, shader_preset);
}
if ( video_driver_get_hw_context()->context_type == RETRO_HW_CONTEXT_DIRECT3D
&& video_driver_get_hw_context()->version_major == 12)
{
d3d12->flags |= D3D12_ST_FLAG_HW_IFACE_ENABLE;
d3d12->hw_iface.interface_type = RETRO_HW_RENDER_INTERFACE_D3D12;
d3d12->hw_iface.interface_version = RETRO_HW_RENDER_INTERFACE_D3D12_VERSION;
d3d12->hw_iface.handle = d3d12;
d3d12->hw_iface.device = d3d12->device;
d3d12->hw_iface.queue = d3d12->queue.handle;
d3d12->hw_iface.required_state = D3D12_RESOURCE_STATE_COPY_SOURCE;
d3d12->hw_iface.set_texture = d3d12_set_hw_render_texture;
d3d12->hw_iface.D3DCompile = D3DCompile;
}
return d3d12;
error:
@ -2332,6 +2353,20 @@ static bool d3d12_gfx_frame(
if (frame && width && height)
{
if (frame == RETRO_HW_FRAME_BUFFER_VALID)
{
if (d3d12->frame.texture[0].desc.Format != d3d12->hw_render_texture_format)
{
d3d12->frame.texture[0].desc.Width = width;
d3d12->frame.texture[0].desc.Height = height;
d3d12->frame.texture[0].desc.Format = d3d12->hw_render_texture_format;
d3d12_release_texture(&d3d12->frame.texture[0]);
d3d12_init_texture(d3d12->device, &d3d12->frame.texture[0]);
d3d12->flags |= D3D12_ST_FLAG_INIT_HISTORY;
}
}
if (d3d12->shader_preset)
{
if (d3d12->shader_preset->luts && d3d12->luts[0].dirty)
@ -2387,11 +2422,51 @@ static bool d3d12_gfx_frame(
if (d3d12->flags & D3D12_ST_FLAG_RESIZE_RTS)
d3d12_init_render_targets(d3d12, width, height);
if(frame == RETRO_HW_FRAME_BUFFER_VALID)
{
D3D12_BOX src_box;
D3D12_TEXTURE_COPY_LOCATION src, dst;
src_box.left = 0;
src_box.top = 0;
src_box.front = 0;
src_box.right = width;
src_box.bottom = height;
src_box.back = 1;
src.pResource = d3d12->hw_render_texture;
src.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
src.SubresourceIndex = 0;
dst.pResource = d3d12->frame.texture[0].handle;
dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
dst.SubresourceIndex = 0;
D3D12_RESOURCE_TRANSITION(
d3d12->queue.cmd,
d3d12->frame.texture[0].handle,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
D3D12_RESOURCE_STATE_COPY_DEST);
D3D12CopyTextureRegion(d3d12->queue.cmd, &dst, 0, 0, 0, &src, &src_box);
D3D12_RESOURCE_TRANSITION(
d3d12->queue.cmd,
d3d12->frame.texture[0].handle,
D3D12_RESOURCE_STATE_COPY_DEST,
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
d3d12->hw_render_texture = NULL;
}
else
{
d3d12_update_texture(width, height, pitch, d3d12->format,
frame, &d3d12->frame.texture[0]);
d3d12_upload_texture(d3d12->queue.cmd, &d3d12->frame.texture[0],
d3d12);
}
}
D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1, &d3d12->frame.vbo_view);
@ -3058,6 +3133,15 @@ static void d3d12_gfx_unload_texture(void* data,
free(texture);
}
static bool d3d12_get_hw_render_interface(
void* data, const struct retro_hw_render_interface** iface)
{
d3d12_video_t* d3d12 = (d3d12_video_t*)data;
*iface = (const struct retro_hw_render_interface*)
&d3d12->hw_iface;
return d3d12->flags & D3D12_ST_FLAG_HW_IFACE_ENABLE;
}
#ifndef __WINRT__
static void d3d12_get_video_output_size(void *data,
unsigned *width, unsigned *height, char *desc, size_t desc_len)
@ -3112,7 +3196,7 @@ static const video_poke_interface_t d3d12_poke_interface = {
NULL, /* grab_mouse_toggle */
d3d12_gfx_get_current_shader,
NULL, /* get_current_software_framebuffer */
NULL, /* get_hw_render_interface */
d3d12_get_hw_render_interface,
#ifdef HAVE_DXGI_HDR
d3d12_set_hdr_max_nits,
d3d12_set_hdr_paper_white_nits,

View File

@ -505,6 +505,10 @@ const char *hw_render_context_name(
if (type == RETRO_HW_CONTEXT_DIRECT3D && major == 11)
return "d3d11";
#endif
#ifdef HAVE_D3D12
if (type == RETRO_HW_CONTEXT_DIRECT3D && major == 12)
return "d3d12";
#endif
#ifdef HAVE_D3D9
#if defined(HAVE_HLSL)
if (type == RETRO_HW_CONTEXT_DIRECT3D && major == 9)

View File

@ -56,4 +56,32 @@ struct retro_hw_render_interface_d3d11
#endif
#ifdef HAVE_D3D12
#include <d3d12.h>
#include <d3dcompiler.h>
#define RETRO_HW_RENDER_INTERFACE_D3D12_VERSION 1
struct retro_hw_render_interface_d3d12
{
/* Must be set to RETRO_HW_RENDER_INTERFACE_D3D12. */
enum retro_hw_render_interface_type interface_type;
/* Must be set to RETRO_HW_RENDER_INTERFACE_D3D12_VERSION. */
unsigned interface_version;
/* Opaque handle to the d3d12 backend in the frontend
* which must be passed along to all function pointers
* in this interface.
*/
void* handle;
ID3D12Device *device;
ID3D12CommandQueue *queue;
pD3DCompile D3DCompile;
D3D12_RESOURCE_STATES required_state;
void (*set_texture)(void* handle, ID3D12Resource* texture, DXGI_FORMAT format);
};
#endif
#endif /* LIBRETRO_DIRECT3D_H__ */

View File

@ -740,7 +740,8 @@ static bool dynamic_verify_hw_context(
return false;
break;
case RETRO_HW_CONTEXT_DIRECT3D:
if (!(string_is_equal(video_ident, "d3d11") && major == 11))
if (!((string_is_equal(video_ident, "d3d11") && major == 11) ||
(string_is_equal(video_ident, "d3d12") && major == 12)))
return false;
break;
default:
@ -834,7 +835,7 @@ static bool dynamic_request_hw_context(enum retro_hw_context_type type,
break;
#endif
#if defined(HAVE_D3D9) || defined(HAVE_D3D11)
#if defined(HAVE_D3D9) || defined(HAVE_D3D11) || defined(HAVE_D3D12)
case RETRO_HW_CONTEXT_DIRECT3D:
switch (major)
{
@ -847,6 +848,11 @@ static bool dynamic_request_hw_context(enum retro_hw_context_type type,
case 11:
RARCH_LOG("Requesting D3D11 context.\n");
break;
#endif
#ifdef HAVE_D3D12
case 12:
RARCH_LOG("Requesting D3D12 context.\n");
break;
#endif
default:
RARCH_LOG("Requesting unknown context.\n");