mirror of
https://github.com/libretro/RetroArch
synced 2025-02-06 00:39:53 +00:00
Merge pull request #6251 from aliaspider/master
(D3D12) menu display driver / font renderer
This commit is contained in:
commit
3391a0b94e
@ -1268,7 +1268,8 @@ ifeq ($(HAVE_D3D11), 1)
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_D3D12), 1)
|
||||
OBJ += gfx/drivers/d3d12.o gfx/common/d3d12_common.o
|
||||
OBJ += gfx/drivers/d3d12.o gfx/common/d3d12_common.o \
|
||||
gfx/drivers_font/d3d12_font.o menu/drivers_display/menu_display_d3d12.o
|
||||
DEFINES += -DHAVE_D3D12
|
||||
endif
|
||||
|
||||
|
@ -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))
|
||||
|
@ -57,7 +57,7 @@ HRESULT WINAPI D3D10CreateDeviceAndSwapChain(
|
||||
d3d10_dll, "D3D10CreateDeviceAndSwapChain");
|
||||
|
||||
if (!fp)
|
||||
return TYPE_E_CANTLOADLIBRARY;
|
||||
return TYPE_E_DLLFUNCTIONNOTFOUND;
|
||||
|
||||
return fp(
|
||||
pAdapter, DriverType, Software, Flags, SDKVersion,
|
||||
|
@ -51,7 +51,7 @@ HRESULT WINAPI D3D11CreateDeviceAndSwapChain(
|
||||
d3d11_dll, "D3D11CreateDeviceAndSwapChain");
|
||||
|
||||
if (!fp)
|
||||
return TYPE_E_CANTLOADLIBRARY;
|
||||
return TYPE_E_DLLFUNCTIONNOTFOUND;
|
||||
|
||||
return fp(
|
||||
pAdapter, DriverType, Software, Flags, pFeatureLevels, FeatureLevels, SDKVersion,
|
||||
|
@ -15,6 +15,8 @@
|
||||
|
||||
#define CINTERFACE
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "d3d12_common.h"
|
||||
#include "dxgi_common.h"
|
||||
#include "d3dcompiler_common.h"
|
||||
@ -75,16 +77,15 @@ HRESULT WINAPI D3D12CreateDevice(
|
||||
d3d12_dll = dylib_load(d3d12_dll_name);
|
||||
|
||||
if (!d3d12_dll)
|
||||
goto error;
|
||||
return TYPE_E_CANTLOADLIBRARY;
|
||||
|
||||
if (!fp)
|
||||
fp = (PFN_D3D12_CREATE_DEVICE)dylib_proc(d3d12_dll, "D3D12CreateDevice");
|
||||
|
||||
if (fp)
|
||||
return fp(pAdapter, MinimumFeatureLevel, riid, ppDevice);
|
||||
if (!fp)
|
||||
return TYPE_E_DLLFUNCTIONNOTFOUND;
|
||||
|
||||
error:
|
||||
return TYPE_E_CANTLOADLIBRARY;
|
||||
return fp(pAdapter, MinimumFeatureLevel, riid, ppDevice);
|
||||
}
|
||||
|
||||
HRESULT WINAPI D3D12GetDebugInterface(REFIID riid, void** ppvDebug)
|
||||
@ -94,16 +95,15 @@ HRESULT WINAPI D3D12GetDebugInterface(REFIID riid, void** ppvDebug)
|
||||
d3d12_dll = dylib_load(d3d12_dll_name);
|
||||
|
||||
if (!d3d12_dll)
|
||||
goto error;
|
||||
return TYPE_E_CANTLOADLIBRARY;
|
||||
|
||||
if (!fp)
|
||||
fp = (PFN_D3D12_GET_DEBUG_INTERFACE)dylib_proc(d3d12_dll, "D3D12GetDebugInterface");
|
||||
|
||||
if (fp)
|
||||
return fp(riid, ppvDebug);
|
||||
if (!fp)
|
||||
return TYPE_E_DLLFUNCTIONNOTFOUND;
|
||||
|
||||
error:
|
||||
return TYPE_E_CANTLOADLIBRARY;
|
||||
return fp(riid, ppvDebug);
|
||||
}
|
||||
|
||||
HRESULT WINAPI D3D12SerializeRootSignature(
|
||||
@ -117,16 +117,15 @@ HRESULT WINAPI D3D12SerializeRootSignature(
|
||||
d3d12_dll = dylib_load(d3d12_dll_name);
|
||||
|
||||
if (!d3d12_dll)
|
||||
goto error;
|
||||
return TYPE_E_CANTLOADLIBRARY;
|
||||
|
||||
if (!fp)
|
||||
fp = (PFN_D3D12_SERIALIZE_ROOT_SIGNATURE)dylib_proc(d3d12_dll, "D3D12SerializeRootSignature");
|
||||
|
||||
if (fp)
|
||||
return fp(pRootSignature, Version, ppBlob, ppErrorBlob);
|
||||
if (!fp)
|
||||
return TYPE_E_DLLFUNCTIONNOTFOUND;
|
||||
|
||||
error:
|
||||
return TYPE_E_CANTLOADLIBRARY;
|
||||
return fp(pRootSignature, Version, ppBlob, ppErrorBlob);
|
||||
}
|
||||
|
||||
HRESULT WINAPI D3D12SerializeVersionedRootSignature(
|
||||
@ -139,17 +138,16 @@ HRESULT WINAPI D3D12SerializeVersionedRootSignature(
|
||||
d3d12_dll = dylib_load(d3d12_dll_name);
|
||||
|
||||
if (!d3d12_dll)
|
||||
goto error;
|
||||
return TYPE_E_CANTLOADLIBRARY;
|
||||
|
||||
if (!fp)
|
||||
fp = (PFN_D3D12_SERIALIZE_VERSIONED_ROOT_SIGNATURE)dylib_proc(
|
||||
d3d12_dll, "D3D12SerializeRootSignature");
|
||||
|
||||
if (fp)
|
||||
return fp(pRootSignature, ppBlob, ppErrorBlob);
|
||||
if (!fp)
|
||||
return TYPE_E_DLLFUNCTIONNOTFOUND;
|
||||
|
||||
error:
|
||||
return TYPE_E_CANTLOADLIBRARY;
|
||||
return fp(pRootSignature, ppBlob, ppErrorBlob);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -195,7 +193,7 @@ bool d3d12_init_queue(d3d12_video_t* d3d12)
|
||||
|
||||
D3D12CreateGraphicsCommandList(
|
||||
d3d12->device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT, d3d12->queue.allocator,
|
||||
d3d12->pipe.handle, &d3d12->queue.cmd);
|
||||
d3d12->pipes[VIDEO_SHADER_STOCK_BLEND], &d3d12->queue.cmd);
|
||||
|
||||
D3D12CloseGraphicsCommandList(d3d12->queue.cmd);
|
||||
|
||||
@ -238,7 +236,7 @@ bool d3d12_init_swapchain(d3d12_video_t* d3d12, int width, int height, HWND hwnd
|
||||
for (int i = 0; i < countof(d3d12->chain.renderTargets); i++)
|
||||
{
|
||||
d3d12->chain.desc_handles[i].ptr =
|
||||
d3d12->pipe.rtv_heap.cpu.ptr + i * d3d12->pipe.rtv_heap.stride;
|
||||
d3d12->desc.rtv_heap.cpu.ptr + i * d3d12->desc.rtv_heap.stride;
|
||||
DXGIGetSwapChainBuffer(d3d12->chain.handle, i, &d3d12->chain.renderTargets[i]);
|
||||
D3D12CreateRenderTargetView(
|
||||
d3d12->device, d3d12->chain.renderTargets[i], NULL, d3d12->chain.desc_handles[i]);
|
||||
@ -258,64 +256,97 @@ static void d3d12_init_descriptor_heap(D3D12Device device, d3d12_descriptor_heap
|
||||
out->cpu = D3D12GetCPUDescriptorHandleForHeapStart(out->handle);
|
||||
out->gpu = D3D12GetGPUDescriptorHandleForHeapStart(out->handle);
|
||||
out->stride = D3D12GetDescriptorHandleIncrementSize(device, out->desc.Type);
|
||||
out->map = (bool*)calloc(out->desc.NumDescriptors, sizeof(bool));
|
||||
}
|
||||
|
||||
static void d3d12_init_sampler(
|
||||
D3D12Device device,
|
||||
d3d12_descriptor_heap_t* heap,
|
||||
descriptor_heap_slot_t heap_index,
|
||||
D3D12_FILTER filter,
|
||||
D3D12_TEXTURE_ADDRESS_MODE address_mode,
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE* dst)
|
||||
static inline void d3d12_release_descriptor_heap(d3d12_descriptor_heap_t* heap)
|
||||
{
|
||||
D3D12_SAMPLER_DESC sampler_desc = { filter, address_mode, address_mode, address_mode };
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE handle = { heap->cpu.ptr + heap_index * heap->stride };
|
||||
free(heap->map);
|
||||
Release(heap->handle);
|
||||
}
|
||||
|
||||
sampler_desc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER;
|
||||
sampler_desc.MaxLOD = D3D12_FLOAT32_MAX;
|
||||
static D3D12_CPU_DESCRIPTOR_HANDLE d3d12_descriptor_heap_slot_alloc(d3d12_descriptor_heap_t* heap)
|
||||
{
|
||||
int i;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE handle = { 0 };
|
||||
|
||||
D3D12CreateSampler(device, &sampler_desc, handle);
|
||||
dst->ptr = heap->gpu.ptr + heap_index * heap->stride;
|
||||
for (i = heap->start; i < heap->desc.NumDescriptors; i++)
|
||||
{
|
||||
if (!heap->map[i])
|
||||
{
|
||||
heap->map[i] = true;
|
||||
handle.ptr = heap->cpu.ptr + i * heap->stride;
|
||||
heap->start = i + 1;
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
/* if you get here try increasing NumDescriptors for this heap */
|
||||
assert(0);
|
||||
return handle;
|
||||
}
|
||||
|
||||
static void
|
||||
d3d12_descriptor_heap_slot_free(d3d12_descriptor_heap_t* heap, D3D12_CPU_DESCRIPTOR_HANDLE handle)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!handle.ptr)
|
||||
return;
|
||||
|
||||
assert(((handle.ptr - heap->cpu.ptr) % heap->stride) == 0);
|
||||
|
||||
i = (handle.ptr - heap->cpu.ptr) / heap->stride;
|
||||
assert(i >= 0 && i < heap->desc.NumDescriptors);
|
||||
assert(heap->map[i]);
|
||||
|
||||
heap->map[i] = false;
|
||||
if (heap->start > i)
|
||||
heap->start = i;
|
||||
}
|
||||
|
||||
bool d3d12_create_root_signature(
|
||||
D3D12Device device, D3D12_ROOT_SIGNATURE_DESC* desc, D3D12RootSignature* out)
|
||||
{
|
||||
D3DBlob signature;
|
||||
D3DBlob error;
|
||||
D3D12SerializeRootSignature(desc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error);
|
||||
|
||||
if (error)
|
||||
{
|
||||
RARCH_ERR(
|
||||
"[D3D12]: CreateRootSignature failed : %s", (const char*)D3DGetBufferPointer(error));
|
||||
Release(error);
|
||||
return false;
|
||||
}
|
||||
|
||||
D3D12CreateRootSignature(
|
||||
device, 0, D3DGetBufferPointer(signature), D3DGetBufferSize(signature), out);
|
||||
Release(signature);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool d3d12_init_descriptors(d3d12_video_t* d3d12)
|
||||
{
|
||||
D3D12_ROOT_SIGNATURE_DESC desc;
|
||||
static const D3D12_DESCRIPTOR_RANGE srv_table[] = {
|
||||
{
|
||||
D3D12_DESCRIPTOR_RANGE_TYPE_SRV,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND,
|
||||
},
|
||||
};
|
||||
static const D3D12_DESCRIPTOR_RANGE sampler_table[] = {
|
||||
{
|
||||
D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND,
|
||||
},
|
||||
};
|
||||
|
||||
D3D12_ROOT_PARAMETER rootParameters[ROOT_ID_MAX];
|
||||
D3D12_ROOT_SIGNATURE_DESC desc;
|
||||
D3D12_DESCRIPTOR_RANGE srv_tbl[] = { { D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1 } };
|
||||
D3D12_DESCRIPTOR_RANGE sampler_tbl[] = { { D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, 1 } };
|
||||
D3D12_ROOT_PARAMETER rootParameters[ROOT_ID_MAX];
|
||||
|
||||
rootParameters[ROOT_ID_TEXTURE_T].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
rootParameters[ROOT_ID_TEXTURE_T].DescriptorTable.NumDescriptorRanges = countof(srv_table);
|
||||
rootParameters[ROOT_ID_TEXTURE_T].DescriptorTable.pDescriptorRanges = srv_table;
|
||||
rootParameters[ROOT_ID_TEXTURE_T].DescriptorTable.NumDescriptorRanges = countof(srv_tbl);
|
||||
rootParameters[ROOT_ID_TEXTURE_T].DescriptorTable.pDescriptorRanges = srv_tbl;
|
||||
rootParameters[ROOT_ID_TEXTURE_T].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
|
||||
|
||||
rootParameters[ROOT_ID_SAMPLER_T].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
||||
rootParameters[ROOT_ID_SAMPLER_T].DescriptorTable.NumDescriptorRanges = countof(sampler_table);
|
||||
rootParameters[ROOT_ID_SAMPLER_T].DescriptorTable.pDescriptorRanges = sampler_table;
|
||||
rootParameters[ROOT_ID_SAMPLER_T].DescriptorTable.NumDescriptorRanges = countof(sampler_tbl);
|
||||
rootParameters[ROOT_ID_SAMPLER_T].DescriptorTable.pDescriptorRanges = sampler_tbl;
|
||||
rootParameters[ROOT_ID_SAMPLER_T].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL;
|
||||
|
||||
rootParameters[ROOT_ID_UBO].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
|
||||
rootParameters[ROOT_ID_UBO].Descriptor.RegisterSpace = 0;
|
||||
rootParameters[ROOT_ID_UBO].Descriptor.ShaderRegister = 0;
|
||||
rootParameters[ROOT_ID_UBO].ShaderVisibility = D3D12_SHADER_VISIBILITY_VERTEX;
|
||||
rootParameters[ROOT_ID_UBO].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
|
||||
|
||||
desc.NumParameters = countof(rootParameters);
|
||||
desc.pParameters = rootParameters;
|
||||
@ -323,121 +354,143 @@ bool d3d12_init_descriptors(d3d12_video_t* d3d12)
|
||||
desc.pStaticSamplers = NULL;
|
||||
desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
|
||||
|
||||
{
|
||||
D3DBlob signature;
|
||||
D3DBlob error;
|
||||
D3D12SerializeRootSignature(&desc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error);
|
||||
d3d12_create_root_signature(d3d12->device, &desc, &d3d12->desc.rootSignature);
|
||||
|
||||
if (error)
|
||||
{
|
||||
RARCH_ERR(
|
||||
"[D3D12]: CreateRootSignature failed :\n%s\n",
|
||||
(const char*)D3DGetBufferPointer(error));
|
||||
Release(error);
|
||||
return false;
|
||||
}
|
||||
srv_tbl[0].NumDescriptors = SLANG_NUM_BINDINGS;
|
||||
sampler_tbl[0].NumDescriptors = SLANG_NUM_BINDINGS;
|
||||
d3d12_create_root_signature(d3d12->device, &desc, &d3d12->desc.sl_rootSignature);
|
||||
|
||||
D3D12CreateRootSignature(
|
||||
d3d12->device, 0, D3DGetBufferPointer(signature), D3DGetBufferSize(signature),
|
||||
&d3d12->pipe.rootSignature);
|
||||
Release(signature);
|
||||
}
|
||||
d3d12->desc.rtv_heap.desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
|
||||
d3d12->desc.rtv_heap.desc.NumDescriptors = countof(d3d12->chain.renderTargets) + GFX_MAX_SHADERS;
|
||||
d3d12->desc.rtv_heap.desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||
d3d12_init_descriptor_heap(d3d12->device, &d3d12->desc.rtv_heap);
|
||||
|
||||
d3d12->pipe.rtv_heap.desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
|
||||
d3d12->pipe.rtv_heap.desc.NumDescriptors = countof(d3d12->chain.renderTargets);
|
||||
d3d12->pipe.rtv_heap.desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
|
||||
d3d12_init_descriptor_heap(d3d12->device, &d3d12->pipe.rtv_heap);
|
||||
d3d12->desc.srv_heap.desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
d3d12->desc.srv_heap.desc.NumDescriptors = 256;
|
||||
d3d12->desc.srv_heap.desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
d3d12_init_descriptor_heap(d3d12->device, &d3d12->desc.srv_heap);
|
||||
|
||||
d3d12->pipe.srv_heap.desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
|
||||
d3d12->pipe.srv_heap.desc.NumDescriptors = SRV_HEAP_SLOT_MAX;
|
||||
d3d12->pipe.srv_heap.desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
d3d12_init_descriptor_heap(d3d12->device, &d3d12->pipe.srv_heap);
|
||||
d3d12->desc.sampler_heap.desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
|
||||
d3d12->desc.sampler_heap.desc.NumDescriptors = 2 * RARCH_WRAP_MAX;
|
||||
d3d12->desc.sampler_heap.desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
d3d12_init_descriptor_heap(d3d12->device, &d3d12->desc.sampler_heap);
|
||||
|
||||
d3d12->pipe.sampler_heap.desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER;
|
||||
d3d12->pipe.sampler_heap.desc.NumDescriptors = SAMPLER_HEAP_SLOT_MAX;
|
||||
d3d12->pipe.sampler_heap.desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
|
||||
d3d12_init_descriptor_heap(d3d12->device, &d3d12->pipe.sampler_heap);
|
||||
|
||||
d3d12_init_sampler(
|
||||
d3d12->device, &d3d12->pipe.sampler_heap, SAMPLER_HEAP_SLOT_LINEAR,
|
||||
D3D12_FILTER_MIN_MAG_MIP_LINEAR, D3D12_TEXTURE_ADDRESS_MODE_BORDER,
|
||||
&d3d12->sampler_linear);
|
||||
d3d12_init_sampler(
|
||||
d3d12->device, &d3d12->pipe.sampler_heap, SAMPLER_HEAP_SLOT_NEAREST,
|
||||
D3D12_FILTER_MIN_MAG_MIP_POINT, D3D12_TEXTURE_ADDRESS_MODE_BORDER,
|
||||
&d3d12->sampler_nearest);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool d3d12_init_pipeline(d3d12_video_t* d3d12)
|
||||
static INLINE D3D12_GPU_DESCRIPTOR_HANDLE
|
||||
d3d12_create_sampler(D3D12Device device, D3D12_SAMPLER_DESC* desc, d3d12_descriptor_heap_t* heap)
|
||||
{
|
||||
D3DBlob vs_code;
|
||||
D3DBlob ps_code;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE cpu_handle = d3d12_descriptor_heap_slot_alloc(heap);
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpu_handle = { cpu_handle.ptr - heap->cpu.ptr + heap->gpu.ptr };
|
||||
|
||||
static const char stock[] =
|
||||
#include "../drivers/d3d_shaders/opaque_sm5.hlsl.h"
|
||||
;
|
||||
D3D12CreateSampler(device, desc, cpu_handle);
|
||||
return gpu_handle;
|
||||
}
|
||||
|
||||
static const D3D12_INPUT_ELEMENT_DESC inputElementDesc[] = {
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d12_vertex_t, position),
|
||||
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d12_vertex_t, texcoord),
|
||||
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(d3d12_vertex_t, color),
|
||||
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
|
||||
if (!d3d_compile(stock, sizeof(stock), NULL, "VSMain", "vs_5_0", &vs_code))
|
||||
return false;
|
||||
|
||||
if (!d3d_compile(stock, sizeof(stock), NULL, "PSMain", "ps_5_0", &ps_code))
|
||||
return false;
|
||||
void d3d12_init_samplers(d3d12_video_t* d3d12)
|
||||
{
|
||||
int i;
|
||||
D3D12_SAMPLER_DESC desc = { D3D12_FILTER_MIN_MAG_MIP_POINT };
|
||||
desc.MaxAnisotropy = 1;
|
||||
desc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER;
|
||||
desc.MinLOD = -D3D12_FLOAT32_MAX;
|
||||
desc.MaxLOD = D3D12_FLOAT32_MAX;
|
||||
|
||||
for (i = 0; i < RARCH_WRAP_MAX; i++)
|
||||
{
|
||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC psodesc = { 0 };
|
||||
psodesc.pRootSignature = d3d12->pipe.rootSignature;
|
||||
psodesc.VS.pShaderBytecode = D3DGetBufferPointer(vs_code);
|
||||
psodesc.VS.BytecodeLength = D3DGetBufferSize(vs_code);
|
||||
psodesc.PS.pShaderBytecode = D3DGetBufferPointer(ps_code);
|
||||
psodesc.PS.BytecodeLength = D3DGetBufferSize(ps_code);
|
||||
psodesc.BlendState.AlphaToCoverageEnable = FALSE;
|
||||
psodesc.BlendState.IndependentBlendEnable = FALSE;
|
||||
psodesc.BlendState.RenderTarget[0].BlendEnable = TRUE;
|
||||
psodesc.BlendState.RenderTarget[0].LogicOpEnable = FALSE;
|
||||
psodesc.BlendState.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA;
|
||||
psodesc.BlendState.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA;
|
||||
psodesc.BlendState.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD;
|
||||
psodesc.BlendState.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_SRC_ALPHA;
|
||||
psodesc.BlendState.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA;
|
||||
psodesc.BlendState.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD;
|
||||
psodesc.BlendState.RenderTarget[0].LogicOp = D3D12_LOGIC_OP_NOOP;
|
||||
psodesc.BlendState.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
|
||||
psodesc.SampleMask = UINT_MAX;
|
||||
psodesc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
|
||||
psodesc.RasterizerState.CullMode = D3D12_CULL_MODE_BACK;
|
||||
psodesc.RasterizerState.FrontCounterClockwise = FALSE;
|
||||
psodesc.RasterizerState.DepthBias = D3D12_DEFAULT_DEPTH_BIAS;
|
||||
psodesc.RasterizerState.DepthBiasClamp = D3D12_DEFAULT_DEPTH_BIAS_CLAMP;
|
||||
psodesc.RasterizerState.SlopeScaledDepthBias = D3D12_DEFAULT_SLOPE_SCALED_DEPTH_BIAS;
|
||||
psodesc.RasterizerState.DepthClipEnable = TRUE;
|
||||
psodesc.RasterizerState.MultisampleEnable = FALSE;
|
||||
psodesc.RasterizerState.AntialiasedLineEnable = FALSE;
|
||||
psodesc.RasterizerState.ForcedSampleCount = 0;
|
||||
psodesc.RasterizerState.ConservativeRaster = D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF;
|
||||
psodesc.DepthStencilState.DepthEnable = FALSE;
|
||||
psodesc.DepthStencilState.StencilEnable = FALSE;
|
||||
psodesc.InputLayout.pInputElementDescs = inputElementDesc;
|
||||
psodesc.InputLayout.NumElements = countof(inputElementDesc);
|
||||
psodesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
|
||||
psodesc.NumRenderTargets = 1;
|
||||
psodesc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
psodesc.SampleDesc.Count = 1;
|
||||
switch (i)
|
||||
{
|
||||
case RARCH_WRAP_BORDER:
|
||||
desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_BORDER;
|
||||
break;
|
||||
|
||||
D3D12CreateGraphicsPipelineState(d3d12->device, &psodesc, &d3d12->pipe.handle);
|
||||
case RARCH_WRAP_EDGE:
|
||||
desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP;
|
||||
break;
|
||||
|
||||
case RARCH_WRAP_REPEAT:
|
||||
desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
|
||||
break;
|
||||
|
||||
case RARCH_WRAP_MIRRORED_REPEAT:
|
||||
desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_MIRROR;
|
||||
break;
|
||||
}
|
||||
desc.AddressV = desc.AddressU;
|
||||
desc.AddressW = desc.AddressU;
|
||||
|
||||
desc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR;
|
||||
d3d12->samplers[RARCH_FILTER_LINEAR][i] =
|
||||
d3d12_create_sampler(d3d12->device, &desc, &d3d12->desc.sampler_heap);
|
||||
|
||||
desc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
|
||||
d3d12->samplers[RARCH_FILTER_NEAREST][i] =
|
||||
d3d12_create_sampler(d3d12->device, &desc, &d3d12->desc.sampler_heap);
|
||||
}
|
||||
}
|
||||
|
||||
D3D12_RENDER_TARGET_BLEND_DESC d3d12_blend_enable_desc = {
|
||||
TRUE,
|
||||
FALSE,
|
||||
D3D12_BLEND_SRC_ALPHA,
|
||||
D3D12_BLEND_INV_SRC_ALPHA,
|
||||
D3D12_BLEND_OP_ADD,
|
||||
D3D12_BLEND_SRC_ALPHA,
|
||||
D3D12_BLEND_INV_SRC_ALPHA,
|
||||
D3D12_BLEND_OP_ADD,
|
||||
D3D12_LOGIC_OP_NOOP,
|
||||
D3D12_COLOR_WRITE_ENABLE_ALL,
|
||||
};
|
||||
|
||||
bool d3d12_init_pipeline(
|
||||
D3D12Device device,
|
||||
D3DBlob vs_code,
|
||||
D3DBlob ps_code,
|
||||
D3DBlob gs_code,
|
||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC* desc,
|
||||
D3D12PipelineState* out)
|
||||
{
|
||||
if (vs_code)
|
||||
{
|
||||
desc->VS.pShaderBytecode = D3DGetBufferPointer(vs_code);
|
||||
desc->VS.BytecodeLength = D3DGetBufferSize(vs_code);
|
||||
}
|
||||
else
|
||||
{
|
||||
desc->VS.pShaderBytecode = NULL;
|
||||
desc->VS.BytecodeLength = 0;
|
||||
}
|
||||
|
||||
Release(vs_code);
|
||||
Release(ps_code);
|
||||
if (ps_code)
|
||||
{
|
||||
desc->PS.pShaderBytecode = D3DGetBufferPointer(ps_code);
|
||||
desc->PS.BytecodeLength = D3DGetBufferSize(ps_code);
|
||||
}
|
||||
else
|
||||
{
|
||||
desc->PS.pShaderBytecode = NULL;
|
||||
desc->PS.BytecodeLength = 0;
|
||||
}
|
||||
|
||||
if (gs_code)
|
||||
{
|
||||
desc->GS.pShaderBytecode = D3DGetBufferPointer(gs_code);
|
||||
desc->GS.BytecodeLength = D3DGetBufferSize(gs_code);
|
||||
}
|
||||
else
|
||||
{
|
||||
desc->GS.pShaderBytecode = NULL;
|
||||
desc->GS.BytecodeLength = 0;
|
||||
}
|
||||
|
||||
desc->SampleMask = UINT_MAX;
|
||||
desc->RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
|
||||
desc->RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
|
||||
desc->NumRenderTargets = 1;
|
||||
desc->SampleDesc.Count = 1;
|
||||
|
||||
D3D12CreateGraphicsPipelineState(device, desc, out);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -463,14 +516,21 @@ d3d12_create_buffer(D3D12Device device, UINT size_in_bytes, D3D12Resource* buffe
|
||||
return D3D12GetGPUVirtualAddress(*buffer);
|
||||
}
|
||||
|
||||
void d3d12_init_texture(
|
||||
D3D12Device device,
|
||||
d3d12_descriptor_heap_t* heap,
|
||||
descriptor_heap_slot_t heap_index,
|
||||
d3d12_texture_t* texture)
|
||||
void d3d12_release_texture(d3d12_texture_t* texture)
|
||||
{
|
||||
if (texture->srv_heap)
|
||||
d3d12_descriptor_heap_slot_free(texture->srv_heap, texture->cpu_descriptor);
|
||||
|
||||
Release(texture->handle);
|
||||
Release(texture->upload_buffer);
|
||||
}
|
||||
void d3d12_init_texture(D3D12Device device, d3d12_texture_t* texture)
|
||||
{
|
||||
bool is_render_target = texture->desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
|
||||
D3D12_FORMAT_SUPPORT1 format_support =
|
||||
D3D12_FORMAT_SUPPORT1_TEXTURE2D | D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE;
|
||||
|
||||
d3d12_release_texture(texture);
|
||||
|
||||
{
|
||||
D3D12_HEAP_PROPERTIES heap_props = { D3D12_HEAP_TYPE_DEFAULT, D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
|
||||
@ -480,21 +540,40 @@ void d3d12_init_texture(
|
||||
texture->desc.DepthOrArraySize = 1;
|
||||
texture->desc.MipLevels = 1;
|
||||
texture->desc.SampleDesc.Count = 1;
|
||||
texture->desc.Format = d3d12_get_closest_match(device, texture->desc.Format, format_support);
|
||||
|
||||
D3D12CreateCommittedResource(
|
||||
device, &heap_props, D3D12_HEAP_FLAG_NONE, &texture->desc,
|
||||
D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, NULL, &texture->handle);
|
||||
}
|
||||
|
||||
D3D12GetCopyableFootprints(
|
||||
device, &texture->desc, 0, 1, 0, &texture->layout, &texture->num_rows,
|
||||
&texture->row_size_in_bytes, &texture->total_bytes);
|
||||
if (texture->srv_heap)
|
||||
{
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC view_desc = { texture->desc.Format };
|
||||
|
||||
view_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
view_desc.Texture2D.MipLevels = texture->desc.MipLevels;
|
||||
|
||||
texture->cpu_descriptor = d3d12_descriptor_heap_slot_alloc(texture->srv_heap);
|
||||
D3D12CreateShaderResourceView(device, texture->handle, &view_desc, texture->cpu_descriptor);
|
||||
texture->gpu_descriptor.ptr =
|
||||
texture->cpu_descriptor.ptr - texture->srv_heap->cpu.ptr + texture->srv_heap->gpu.ptr;
|
||||
}
|
||||
|
||||
if (is_render_target)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D12_HEAP_PROPERTIES heap_props = { D3D12_HEAP_TYPE_UPLOAD, D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
|
||||
D3D12_MEMORY_POOL_UNKNOWN, 1, 1 };
|
||||
D3D12_RESOURCE_DESC buffer_desc = { D3D12_RESOURCE_DIMENSION_BUFFER };
|
||||
|
||||
D3D12GetCopyableFootprints(
|
||||
device, &texture->desc, 0, 1, 0, &texture->layout, &texture->num_rows,
|
||||
&texture->row_size_in_bytes, &texture->total_bytes);
|
||||
|
||||
buffer_desc.Width = texture->total_bytes;
|
||||
buffer_desc.Height = 1;
|
||||
buffer_desc.DepthOrArraySize = 1;
|
||||
@ -506,23 +585,29 @@ void d3d12_init_texture(
|
||||
device, &heap_props, D3D12_HEAP_FLAG_NONE, &buffer_desc,
|
||||
D3D12_RESOURCE_STATE_GENERIC_READ, NULL, &texture->upload_buffer);
|
||||
}
|
||||
|
||||
{
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE handle;
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC view_desc = { DXGI_FORMAT_UNKNOWN };
|
||||
|
||||
view_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
|
||||
view_desc.Format = texture->desc.Format;
|
||||
view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
|
||||
view_desc.Texture2D.MipLevels = texture->desc.MipLevels;
|
||||
|
||||
handle.ptr = heap->cpu.ptr + heap_index * heap->stride;
|
||||
|
||||
D3D12CreateShaderResourceView(device, texture->handle, &view_desc, handle);
|
||||
texture->gpu_descriptor.ptr = heap->gpu.ptr + heap_index * heap->stride;
|
||||
}
|
||||
}
|
||||
|
||||
void d3d12_update_texture(
|
||||
int width,
|
||||
int height,
|
||||
int pitch,
|
||||
DXGI_FORMAT format,
|
||||
const void* data,
|
||||
d3d12_texture_t* texture)
|
||||
{
|
||||
uint8_t* dst;
|
||||
D3D12_RANGE read_range = { 0, 0 };
|
||||
|
||||
D3D12Map(texture->upload_buffer, 0, &read_range, (void**)&dst);
|
||||
|
||||
dxgi_copy(
|
||||
width, height, format, pitch, data, texture->desc.Format,
|
||||
texture->layout.Footprint.RowPitch, dst + texture->layout.Offset);
|
||||
|
||||
D3D12Unmap(texture->upload_buffer, 0, NULL);
|
||||
|
||||
texture->dirty = true;
|
||||
}
|
||||
void d3d12_upload_texture(D3D12GraphicsCommandList cmd, d3d12_texture_t* texture)
|
||||
{
|
||||
D3D12_TEXTURE_COPY_LOCATION src = { 0 };
|
||||
|
@ -101,11 +101,13 @@ static INLINE ULONG D3D12ReleaseResource(void* resource)
|
||||
static INLINE HRESULT
|
||||
D3D12Map(void* resource, UINT subresource, D3D12_RANGE* read_range, void** data)
|
||||
{
|
||||
return ((ID3D12Resource*)resource)->lpVtbl->Map((ID3D12Resource*)resource, subresource, read_range, data);
|
||||
return ((ID3D12Resource*)resource)
|
||||
->lpVtbl->Map((ID3D12Resource*)resource, subresource, read_range, data);
|
||||
}
|
||||
static INLINE void D3D12Unmap(void* resource, UINT subresource, D3D12_RANGE* written_range)
|
||||
{
|
||||
((ID3D12Resource*)resource)->lpVtbl->Unmap((ID3D12Resource*)resource, subresource, written_range);
|
||||
((ID3D12Resource*)resource)
|
||||
->lpVtbl->Unmap((ID3D12Resource*)resource, subresource, written_range);
|
||||
}
|
||||
static INLINE D3D12_GPU_VIRTUAL_ADDRESS D3D12GetGPUVirtualAddress(void* resource)
|
||||
{
|
||||
@ -121,7 +123,8 @@ static INLINE HRESULT D3D12WriteToSubresource(
|
||||
{
|
||||
return ((ID3D12Resource*)resource)
|
||||
->lpVtbl->WriteToSubresource(
|
||||
(ID3D12Resource*)resource, dst_subresource, dst_box, src_data, src_row_pitch, src_depth_pitch);
|
||||
(ID3D12Resource*)resource, dst_subresource, dst_box, src_data, src_row_pitch,
|
||||
src_depth_pitch);
|
||||
}
|
||||
static INLINE HRESULT D3D12ReadFromSubresource(
|
||||
void* resource,
|
||||
@ -133,7 +136,8 @@ static INLINE HRESULT D3D12ReadFromSubresource(
|
||||
{
|
||||
return ((ID3D12Resource*)resource)
|
||||
->lpVtbl->ReadFromSubresource(
|
||||
(ID3D12Resource*)resource, dst_data, dst_row_pitch, dst_depth_pitch, src_subresource, src_box);
|
||||
(ID3D12Resource*)resource, dst_data, dst_row_pitch, dst_depth_pitch, src_subresource,
|
||||
src_box);
|
||||
}
|
||||
static INLINE HRESULT D3D12GetHeapProperties(
|
||||
void* resource, D3D12_HEAP_PROPERTIES* heap_properties, D3D12_HEAP_FLAGS* heap_flags)
|
||||
@ -639,8 +643,7 @@ static INLINE UINT D3D12GetNodeCount(D3D12Device device)
|
||||
static INLINE HRESULT D3D12CreateCommandQueue(
|
||||
D3D12Device device, D3D12_COMMAND_QUEUE_DESC* desc, ID3D12CommandQueue** out)
|
||||
{
|
||||
return device->lpVtbl->CreateCommandQueue(
|
||||
device, desc, uuidof(ID3D12CommandQueue), (void**)out);
|
||||
return device->lpVtbl->CreateCommandQueue(device, desc, uuidof(ID3D12CommandQueue), (void**)out);
|
||||
}
|
||||
static INLINE HRESULT D3D12CreateCommandAllocator(
|
||||
D3D12Device device, D3D12_COMMAND_LIST_TYPE type, ID3D12CommandAllocator** out)
|
||||
@ -1207,8 +1210,7 @@ static INLINE void D3D12ExecuteGraphicsCommandLists(
|
||||
static INLINE HRESULT
|
||||
DXGIGetSwapChainBuffer(DXGISwapChain swapchain, UINT buffer, D3D12Resource* surface)
|
||||
{
|
||||
return swapchain->lpVtbl->GetBuffer(
|
||||
swapchain, buffer, uuidof(ID3D12Resource), (void**)surface);
|
||||
return swapchain->lpVtbl->GetBuffer(swapchain, buffer, uuidof(ID3D12Resource), (void**)surface);
|
||||
}
|
||||
static INLINE void D3D12SetDescriptorHeaps(
|
||||
D3D12GraphicsCommandList command_list,
|
||||
@ -1250,9 +1252,12 @@ D3D12GetGPUDescriptorHandleForHeapStart(D3D12DescriptorHeap descriptor_heap)
|
||||
/* internal */
|
||||
|
||||
#include <retro_math.h>
|
||||
#include <retro_common_api.h>
|
||||
#include <gfx/math/matrix_4x4.h>
|
||||
|
||||
#include "../common/d3dcompiler_common.h"
|
||||
#include "../video_driver.h"
|
||||
#include "../drivers_shader/slang_process.h"
|
||||
|
||||
typedef struct d3d12_vertex_t
|
||||
{
|
||||
@ -1261,6 +1266,24 @@ typedef struct d3d12_vertex_t
|
||||
float color[4];
|
||||
} d3d12_vertex_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
float x, y, w, h;
|
||||
} pos;
|
||||
struct
|
||||
{
|
||||
float u, v, w, h;
|
||||
} coords;
|
||||
UINT32 colors[4];
|
||||
struct
|
||||
{
|
||||
float scaling;
|
||||
float rotation;
|
||||
} params;
|
||||
} d3d12_sprite_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
D3D12DescriptorHeap handle; /* descriptor pool */
|
||||
@ -1268,7 +1291,8 @@ typedef struct
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE cpu; /* descriptor */
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpu; /* descriptor */
|
||||
UINT stride;
|
||||
UINT count;
|
||||
bool* map;
|
||||
int start;
|
||||
} d3d12_descriptor_heap_t;
|
||||
|
||||
typedef struct
|
||||
@ -1276,14 +1300,39 @@ typedef struct
|
||||
D3D12Resource handle;
|
||||
D3D12Resource upload_buffer;
|
||||
D3D12_RESOURCE_DESC desc;
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE cpu_descriptor;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE gpu_descriptor;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE sampler;
|
||||
D3D12_PLACED_SUBRESOURCE_FOOTPRINT layout;
|
||||
UINT num_rows;
|
||||
UINT64 row_size_in_bytes;
|
||||
UINT64 total_bytes;
|
||||
d3d12_descriptor_heap_t* srv_heap;
|
||||
bool dirty;
|
||||
} d3d12_texture_t;
|
||||
|
||||
#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
|
||||
{
|
||||
unsigned cur_mon_id;
|
||||
@ -1303,12 +1352,12 @@ typedef struct
|
||||
|
||||
struct
|
||||
{
|
||||
D3D12PipelineState handle;
|
||||
D3D12RootSignature rootSignature; /* descriptor layout */
|
||||
d3d12_descriptor_heap_t srv_heap; /* ShaderResouceView descritor heap */
|
||||
d3d12_descriptor_heap_t rtv_heap; /* RenderTargetView descritor heap */
|
||||
D3D12RootSignature sl_rootSignature; /* descriptor layout */
|
||||
D3D12RootSignature rootSignature; /* descriptor layout */
|
||||
d3d12_descriptor_heap_t srv_heap; /* ShaderResouceView descritor heap */
|
||||
d3d12_descriptor_heap_t rtv_heap; /* RenderTargetView descritor heap */
|
||||
d3d12_descriptor_heap_t sampler_heap;
|
||||
} pipe;
|
||||
} desc;
|
||||
|
||||
struct
|
||||
{
|
||||
@ -1329,7 +1378,6 @@ typedef struct
|
||||
D3D12Resource vbo;
|
||||
D3D12_VERTEX_BUFFER_VIEW vbo_view;
|
||||
d3d12_texture_t texture;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE sampler;
|
||||
D3D12_VIEWPORT viewport;
|
||||
D3D12_RECT scissorRect;
|
||||
int rotation;
|
||||
@ -1337,71 +1385,96 @@ typedef struct
|
||||
|
||||
struct
|
||||
{
|
||||
D3D12Resource vbo;
|
||||
D3D12_VERTEX_BUFFER_VIEW vbo_view;
|
||||
d3d12_texture_t texture;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE sampler;
|
||||
D3D12Resource vbo;
|
||||
D3D12_VERTEX_BUFFER_VIEW vbo_view;
|
||||
d3d12_texture_t texture;
|
||||
|
||||
float alpha;
|
||||
bool enabled;
|
||||
bool fullscreen;
|
||||
} menu;
|
||||
|
||||
struct
|
||||
{
|
||||
D3D12PipelineState pipe;
|
||||
D3D12PipelineState pipe_font;
|
||||
D3D12Resource vbo;
|
||||
D3D12_VERTEX_BUFFER_VIEW vbo_view;
|
||||
int offset;
|
||||
int capacity;
|
||||
bool enabled;
|
||||
} sprites;
|
||||
|
||||
D3D12PipelineState pipes[GFX_MAX_SHADERS];
|
||||
d3d12_uniform_t ubo_values;
|
||||
D3D12Resource ubo;
|
||||
D3D12_CONSTANT_BUFFER_VIEW_DESC ubo_view;
|
||||
DXGI_FORMAT format;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE sampler_linear;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE sampler_nearest;
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE samplers[RARCH_FILTER_MAX][RARCH_WRAP_MAX];
|
||||
math_matrix_4x4 mvp, mvp_no_rot;
|
||||
struct video_viewport vp;
|
||||
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;
|
||||
#endif
|
||||
} d3d12_video_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
typedef enum {
|
||||
ROOT_ID_TEXTURE_T = 0,
|
||||
ROOT_ID_SAMPLER_T,
|
||||
ROOT_ID_UBO,
|
||||
ROOT_ID_MAX,
|
||||
} root_signature_parameter_index_t;
|
||||
|
||||
typedef enum {
|
||||
SAMPLER_HEAP_SLOT_LINEAR = 0,
|
||||
SAMPLER_HEAP_SLOT_NEAREST,
|
||||
SAMPLER_HEAP_SLOT_MAX,
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
SRV_HEAP_SLOT_FRAME_TEXTURE = 0,
|
||||
SRV_HEAP_SLOT_MENU_TEXTURE,
|
||||
SRV_HEAP_SLOT_CUSTOM,
|
||||
SRV_HEAP_SLOT_MAX = 16
|
||||
} descriptor_heap_slot_t;
|
||||
extern D3D12_RENDER_TARGET_BLEND_DESC d3d12_blend_enable_desc;
|
||||
|
||||
bool d3d12_init_base(d3d12_video_t* d3d12);
|
||||
|
||||
bool d3d12_init_descriptors(d3d12_video_t* d3d12);
|
||||
bool d3d12_init_pipeline(d3d12_video_t* d3d12);
|
||||
void d3d12_init_samplers(d3d12_video_t* d3d12);
|
||||
|
||||
bool d3d12_init_pipeline(
|
||||
D3D12Device device,
|
||||
D3DBlob vs_code,
|
||||
D3DBlob ps_code,
|
||||
D3DBlob gs_code,
|
||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC* desc,
|
||||
D3D12PipelineState* out);
|
||||
|
||||
bool d3d12_init_swapchain(d3d12_video_t* d3d12, int width, int height, HWND hwnd);
|
||||
|
||||
bool d3d12_init_queue(d3d12_video_t* d3d12);
|
||||
|
||||
D3D12_GPU_VIRTUAL_ADDRESS
|
||||
d3d12_create_buffer(D3D12Device device, UINT size_in_bytes, D3D12Resource* buffer);
|
||||
|
||||
void d3d12_init_texture(
|
||||
D3D12Device device,
|
||||
d3d12_descriptor_heap_t* heap,
|
||||
descriptor_heap_slot_t heap_index,
|
||||
d3d12_texture_t* tex);
|
||||
void d3d12_init_texture(D3D12Device device, d3d12_texture_t* tex);
|
||||
void d3d12_release_texture(d3d12_texture_t* texture);
|
||||
|
||||
void d3d12_update_texture(
|
||||
int width,
|
||||
int height,
|
||||
int pitch,
|
||||
DXGI_FORMAT format,
|
||||
const void* data,
|
||||
d3d12_texture_t* texture);
|
||||
|
||||
void d3d12_upload_texture(D3D12GraphicsCommandList cmd, d3d12_texture_t* texture);
|
||||
|
||||
void d3d12_create_fullscreen_quad_vbo(
|
||||
D3D12Device device, D3D12_VERTEX_BUFFER_VIEW* view, D3D12Resource* vbo);
|
||||
|
||||
DXGI_FORMAT d3d12_get_closest_match(
|
||||
D3D12Device device, DXGI_FORMAT desired_format, D3D12_FORMAT_SUPPORT1 desired_format_support);
|
||||
|
||||
#if !defined(__cplusplus) || defined(CINTERFACE)
|
||||
static INLINE void d3d12_resource_transition(
|
||||
D3D12GraphicsCommandList cmd,
|
||||
D3D12Resource resource,
|
||||
@ -1429,35 +1502,13 @@ d3d12_set_sampler(D3D12GraphicsCommandList cmd, D3D12_GPU_DESCRIPTOR_HANDLE samp
|
||||
D3D12SetGraphicsRootDescriptorTable(cmd, ROOT_ID_SAMPLER_T, sampler);
|
||||
}
|
||||
|
||||
static INLINE void d3d12_update_texture(
|
||||
int width,
|
||||
int height,
|
||||
int pitch,
|
||||
DXGI_FORMAT format,
|
||||
const void* data,
|
||||
d3d12_texture_t* texture)
|
||||
static INLINE void
|
||||
d3d12_set_texture_and_sampler(D3D12GraphicsCommandList cmd, const d3d12_texture_t* texture)
|
||||
{
|
||||
uint8_t* dst;
|
||||
D3D12_RANGE read_range = { 0, 0 };
|
||||
|
||||
D3D12Map(texture->upload_buffer, 0, &read_range, (void**)&dst);
|
||||
|
||||
dxgi_copy(
|
||||
width, height, format, pitch, data, texture->desc.Format,
|
||||
texture->layout.Footprint.RowPitch, dst + texture->layout.Offset);
|
||||
|
||||
D3D12Unmap(texture->upload_buffer, 0, NULL);
|
||||
|
||||
texture->dirty = true;
|
||||
D3D12SetGraphicsRootDescriptorTable(cmd, ROOT_ID_TEXTURE_T, texture->gpu_descriptor);
|
||||
D3D12SetGraphicsRootDescriptorTable(cmd, ROOT_ID_SAMPLER_T, texture->sampler);
|
||||
}
|
||||
|
||||
DXGI_FORMAT d3d12_get_closest_match(
|
||||
D3D12Device device, DXGI_FORMAT desired_format, D3D12_FORMAT_SUPPORT1 desired_format_support);
|
||||
#endif
|
||||
|
||||
static INLINE DXGI_FORMAT
|
||||
d3d12_get_closest_match_texture2D(D3D12Device device, DXGI_FORMAT desired_format)
|
||||
{
|
||||
return d3d12_get_closest_match(
|
||||
device, desired_format,
|
||||
D3D12_FORMAT_SUPPORT1_TEXTURE2D | D3D12_FORMAT_SUPPORT1_SHADER_SAMPLE);
|
||||
}
|
||||
RETRO_END_DECLS
|
||||
|
@ -59,12 +59,12 @@ HRESULT WINAPI D3DCompile(
|
||||
if (!fp)
|
||||
fp = (pD3DCompile)dylib_proc(d3dcompiler_dll, "D3DCompile");
|
||||
|
||||
if (fp)
|
||||
return fp(
|
||||
pSrcData, SrcDataSize, pSourceName, pDefines, pInclude, pEntrypoint, pTarget, Flags1,
|
||||
Flags2, ppCode, ppErrorMsgs);
|
||||
if (!fp)
|
||||
return TYPE_E_DLLFUNCTIONNOTFOUND;
|
||||
|
||||
return TYPE_E_CANTLOADLIBRARY;
|
||||
return fp(
|
||||
pSrcData, SrcDataSize, pSourceName, pDefines, pInclude, pEntrypoint, pTarget, Flags1,
|
||||
Flags2, ppCode, ppErrorMsgs);
|
||||
}
|
||||
|
||||
HRESULT WINAPI D3DCompileFromFile(
|
||||
@ -79,9 +79,8 @@ HRESULT WINAPI D3DCompileFromFile(
|
||||
ID3DBlob** ppErrorMsgs)
|
||||
{
|
||||
typedef HRESULT(WINAPI * pD3DCompileFromFile)(
|
||||
LPCWSTR pFileName, const D3D_SHADER_MACRO* pDefines, ID3DInclude* pInclude,
|
||||
LPCSTR pEntrypoint, LPCSTR pTarget, UINT Flags1, UINT Flags2, ID3DBlob** ppCode,
|
||||
ID3DBlob** ppErrorMsgs);
|
||||
LPCWSTR, const D3D_SHADER_MACRO*, ID3DInclude*, LPCSTR, LPCSTR, UINT, UINT, ID3DBlob**,
|
||||
ID3DBlob**);
|
||||
static pD3DCompileFromFile fp;
|
||||
const char** dll_name = d3dcompiler_dll_list;
|
||||
while (!d3dcompiler_dll && *dll_name)
|
||||
@ -93,19 +92,17 @@ HRESULT WINAPI D3DCompileFromFile(
|
||||
if (!fp)
|
||||
fp = (pD3DCompileFromFile)dylib_proc(d3dcompiler_dll, "D3DCompileFromFile");
|
||||
|
||||
if (fp)
|
||||
return fp(
|
||||
pFileName, pDefines, pInclude, pEntrypoint, pTarget, Flags1, Flags2, ppCode,
|
||||
ppErrorMsgs);
|
||||
if (!fp)
|
||||
return TYPE_E_DLLFUNCTIONNOTFOUND;
|
||||
|
||||
return TYPE_E_CANTLOADLIBRARY;
|
||||
return fp(
|
||||
pFileName, pDefines, pInclude, pEntrypoint, pTarget, Flags1, Flags2, ppCode, ppErrorMsgs);
|
||||
}
|
||||
|
||||
HRESULT WINAPI
|
||||
D3DReflect(LPCVOID pSrcData, SIZE_T SrcDataSize, REFIID pInterface, void** ppReflector)
|
||||
{
|
||||
typedef HRESULT(WINAPI * pD3DCompileFromFile)(
|
||||
LPCVOID pSrcData, SIZE_T SrcDataSize, REFIID pInterface, void** ppReflector);
|
||||
typedef HRESULT(WINAPI * pD3DCompileFromFile)(LPCVOID, SIZE_T, REFIID, void**);
|
||||
static pD3DCompileFromFile fp;
|
||||
|
||||
const char** dll_name = d3dcompiler_dll_list;
|
||||
@ -118,10 +115,10 @@ HRESULT WINAPI
|
||||
if (!fp)
|
||||
fp = (pD3DCompileFromFile)dylib_proc(d3dcompiler_dll, "D3DReflect");
|
||||
|
||||
if (fp)
|
||||
return fp(pSrcData, SrcDataSize, pInterface, ppReflector);
|
||||
if (!fp)
|
||||
return TYPE_E_DLLFUNCTIONNOTFOUND;
|
||||
|
||||
return TYPE_E_CANTLOADLIBRARY;
|
||||
return fp(pSrcData, SrcDataSize, pInterface, ppReflector);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -47,7 +47,7 @@ HRESULT WINAPI CreateDXGIFactory1(REFIID riid, void** ppFactory)
|
||||
fp = (HRESULT(WINAPI*)(REFIID, void**))dylib_proc(dxgi_dll, "CreateDXGIFactory1");
|
||||
|
||||
if (!fp)
|
||||
return TYPE_E_CANTLOADLIBRARY;
|
||||
return TYPE_E_DLLFUNCTIONNOTFOUND;
|
||||
|
||||
return fp(riid, ppFactory);
|
||||
}
|
||||
|
@ -364,13 +364,8 @@ static void d3d11_gfx_free(void* data)
|
||||
d3d11_release_shader(&d3d11->sprites.shader_font);
|
||||
Release(d3d11->sprites.vbo);
|
||||
|
||||
d3d11_release_shader(&d3d11->shaders[VIDEO_SHADER_STOCK_BLEND]);
|
||||
d3d11_release_shader(&d3d11->shaders[VIDEO_SHADER_MENU]);
|
||||
d3d11_release_shader(&d3d11->shaders[VIDEO_SHADER_MENU_2]);
|
||||
d3d11_release_shader(&d3d11->shaders[VIDEO_SHADER_MENU_3]);
|
||||
d3d11_release_shader(&d3d11->shaders[VIDEO_SHADER_MENU_4]);
|
||||
d3d11_release_shader(&d3d11->shaders[VIDEO_SHADER_MENU_5]);
|
||||
d3d11_release_shader(&d3d11->shaders[VIDEO_SHADER_MENU_6]);
|
||||
for (i = 0; i < GFX_MAX_SHADERS; i++)
|
||||
d3d11_release_shader(&d3d11->shaders[i]);
|
||||
|
||||
Release(d3d11->menu_pipeline_vbo);
|
||||
Release(d3d11->blend_pipeline);
|
||||
|
@ -16,26 +16,35 @@
|
||||
#define CINTERFACE
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <string/stdstring.h>
|
||||
|
||||
#include "../video_driver.h"
|
||||
#include "../font_driver.h"
|
||||
#include "../common/win32_common.h"
|
||||
#include "../common/dxgi_common.h"
|
||||
#include "../common/d3d12_common.h"
|
||||
#include "../common/d3dcompiler_common.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;
|
||||
d3d12_video_t* d3d12 = (d3d12_video_t*)data;
|
||||
|
||||
if (smooth)
|
||||
d3d12->frame.sampler = d3d12->sampler_linear;
|
||||
else
|
||||
d3d12->frame.sampler = d3d12->sampler_nearest;
|
||||
for (i = 0; i < RARCH_WRAP_MAX; i++)
|
||||
{
|
||||
if (smooth)
|
||||
d3d12->samplers[RARCH_FILTER_UNSPEC][i] = d3d12->samplers[RARCH_FILTER_LINEAR][i];
|
||||
else
|
||||
d3d12->samplers[RARCH_FILTER_UNSPEC][i] = d3d12->samplers[RARCH_FILTER_NEAREST][i];
|
||||
}
|
||||
}
|
||||
|
||||
static void d3d12_gfx_set_rotation(void* data, unsigned rotation)
|
||||
@ -45,7 +54,7 @@ static void d3d12_gfx_set_rotation(void* data, unsigned rotation)
|
||||
D3D12_RANGE read_range = { 0, 0 };
|
||||
d3d12_video_t* d3d12 = (d3d12_video_t*)data;
|
||||
|
||||
if(!d3d12)
|
||||
if (!d3d12)
|
||||
return;
|
||||
|
||||
d3d12->frame.rotation = rotation;
|
||||
@ -64,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;
|
||||
|
||||
@ -80,12 +89,307 @@ static void d3d12_update_viewport(void* data, bool force_full)
|
||||
d3d12->resize_viewport = false;
|
||||
}
|
||||
|
||||
static void*
|
||||
static bool d3d12_gfx_init_pipelines(d3d12_video_t* d3d12)
|
||||
{
|
||||
D3DBlob vs_code = NULL;
|
||||
D3DBlob ps_code = NULL;
|
||||
D3DBlob gs_code = NULL;
|
||||
D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = { 0 };
|
||||
|
||||
desc.BlendState.RenderTarget[0] = d3d12_blend_enable_desc;
|
||||
desc.pRootSignature = d3d12->desc.rootSignature;
|
||||
desc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
|
||||
{
|
||||
static const char shader[] =
|
||||
#include "../drivers/d3d_shaders/opaque_sm5.hlsl.h"
|
||||
;
|
||||
|
||||
static const D3D12_INPUT_ELEMENT_DESC inputElementDesc[] = {
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d12_vertex_t, position),
|
||||
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d12_vertex_t, texcoord),
|
||||
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(d3d12_vertex_t, color),
|
||||
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
|
||||
if (!d3d_compile(shader, sizeof(shader), NULL, "VSMain", "vs_5_0", &vs_code))
|
||||
goto error;
|
||||
if (!d3d_compile(shader, sizeof(shader), NULL, "PSMain", "ps_5_0", &ps_code))
|
||||
goto error;
|
||||
|
||||
desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
|
||||
desc.InputLayout.pInputElementDescs = inputElementDesc;
|
||||
desc.InputLayout.NumElements = countof(inputElementDesc);
|
||||
|
||||
if (!d3d12_init_pipeline(
|
||||
d3d12->device, vs_code, ps_code, NULL, &desc,
|
||||
&d3d12->pipes[VIDEO_SHADER_STOCK_BLEND]))
|
||||
goto error;
|
||||
|
||||
Release(vs_code);
|
||||
Release(ps_code);
|
||||
vs_code = NULL;
|
||||
ps_code = NULL;
|
||||
}
|
||||
{
|
||||
static const char shader[] =
|
||||
#include "d3d_shaders/sprite_sm4.hlsl.h"
|
||||
;
|
||||
|
||||
D3D12_INPUT_ELEMENT_DESC inputElementDesc[] = {
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(d3d12_sprite_t, pos),
|
||||
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(d3d12_sprite_t, coords),
|
||||
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, offsetof(d3d12_sprite_t, colors[0]),
|
||||
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 1, DXGI_FORMAT_R8G8B8A8_UNORM, 0, offsetof(d3d12_sprite_t, colors[1]),
|
||||
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 2, DXGI_FORMAT_R8G8B8A8_UNORM, 0, offsetof(d3d12_sprite_t, colors[2]),
|
||||
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
|
||||
{ "COLOR", 3, DXGI_FORMAT_R8G8B8A8_UNORM, 0, offsetof(d3d12_sprite_t, colors[3]),
|
||||
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
|
||||
{ "PARAMS", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d12_sprite_t, params),
|
||||
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
|
||||
if (!d3d_compile(shader, sizeof(shader), NULL, "VSMain", "vs_5_0", &vs_code))
|
||||
goto error;
|
||||
if (!d3d_compile(shader, sizeof(shader), NULL, "PSMain", "ps_5_0", &ps_code))
|
||||
goto error;
|
||||
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);
|
||||
|
||||
if (!d3d12_init_pipeline(
|
||||
d3d12->device, vs_code, ps_code, gs_code, &desc, &d3d12->sprites.pipe))
|
||||
goto error;
|
||||
|
||||
Release(ps_code);
|
||||
ps_code = NULL;
|
||||
|
||||
if (!d3d_compile(shader, sizeof(shader), NULL, "PSMainA8", "ps_5_0", &ps_code))
|
||||
goto error;
|
||||
|
||||
if (!d3d12_init_pipeline(
|
||||
d3d12->device, vs_code, ps_code, gs_code, &desc, &d3d12->sprites.pipe_font))
|
||||
goto error;
|
||||
|
||||
Release(vs_code);
|
||||
Release(ps_code);
|
||||
Release(gs_code);
|
||||
vs_code = NULL;
|
||||
ps_code = NULL;
|
||||
gs_code = NULL;
|
||||
}
|
||||
|
||||
{
|
||||
static const char simple_snow[] =
|
||||
#include "d3d_shaders/simple_snow_sm4.hlsl.h"
|
||||
;
|
||||
static const char snow[] =
|
||||
#include "d3d_shaders/snow_sm4.hlsl.h"
|
||||
;
|
||||
static const char bokeh[] =
|
||||
#include "d3d_shaders/bokeh_sm4.hlsl.h"
|
||||
;
|
||||
static const char snowflake[] =
|
||||
#include "d3d_shaders/snowflake_sm4.hlsl.h"
|
||||
;
|
||||
|
||||
D3D12_INPUT_ELEMENT_DESC inputElementDesc[] = {
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d12_vertex_t, position),
|
||||
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d12_vertex_t, texcoord),
|
||||
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
|
||||
desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
|
||||
desc.InputLayout.pInputElementDescs = inputElementDesc;
|
||||
desc.InputLayout.NumElements = countof(inputElementDesc);
|
||||
|
||||
if (!d3d_compile(simple_snow, sizeof(simple_snow), NULL, "VSMain", "vs_5_0", &vs_code))
|
||||
goto error;
|
||||
if (!d3d_compile(simple_snow, sizeof(simple_snow), NULL, "PSMain", "ps_5_0", &ps_code))
|
||||
goto error;
|
||||
|
||||
if (!d3d12_init_pipeline(
|
||||
d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pipes[VIDEO_SHADER_MENU_3]))
|
||||
goto error;
|
||||
|
||||
Release(vs_code);
|
||||
Release(ps_code);
|
||||
vs_code = NULL;
|
||||
ps_code = NULL;
|
||||
|
||||
if (!d3d_compile(snow, sizeof(snow), NULL, "VSMain", "vs_5_0", &vs_code))
|
||||
goto error;
|
||||
if (!d3d_compile(snow, sizeof(snow), NULL, "PSMain", "ps_5_0", &ps_code))
|
||||
goto error;
|
||||
|
||||
if (!d3d12_init_pipeline(
|
||||
d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pipes[VIDEO_SHADER_MENU_4]))
|
||||
goto error;
|
||||
|
||||
Release(vs_code);
|
||||
Release(ps_code);
|
||||
vs_code = NULL;
|
||||
ps_code = NULL;
|
||||
|
||||
if (!d3d_compile(bokeh, sizeof(bokeh), NULL, "VSMain", "vs_5_0", &vs_code))
|
||||
goto error;
|
||||
if (!d3d_compile(bokeh, sizeof(bokeh), NULL, "PSMain", "ps_5_0", &ps_code))
|
||||
goto error;
|
||||
|
||||
if (!d3d12_init_pipeline(
|
||||
d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pipes[VIDEO_SHADER_MENU_5]))
|
||||
goto error;
|
||||
|
||||
Release(vs_code);
|
||||
Release(ps_code);
|
||||
vs_code = NULL;
|
||||
ps_code = NULL;
|
||||
|
||||
if (!d3d_compile(snowflake, sizeof(snowflake), NULL, "VSMain", "vs_5_0", &vs_code))
|
||||
goto error;
|
||||
if (!d3d_compile(snowflake, sizeof(snowflake), NULL, "PSMain", "ps_5_0", &ps_code))
|
||||
goto error;
|
||||
|
||||
if (!d3d12_init_pipeline(
|
||||
d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pipes[VIDEO_SHADER_MENU_6]))
|
||||
goto error;
|
||||
|
||||
Release(vs_code);
|
||||
Release(ps_code);
|
||||
vs_code = NULL;
|
||||
ps_code = NULL;
|
||||
}
|
||||
|
||||
{
|
||||
static const char ribbon[] =
|
||||
#include "d3d_shaders/ribbon_sm4.hlsl.h"
|
||||
;
|
||||
static const char ribbon_simple[] =
|
||||
#include "d3d_shaders/ribbon_simple_sm4.hlsl.h"
|
||||
;
|
||||
|
||||
D3D12_INPUT_ELEMENT_DESC inputElementDesc[] = {
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0,
|
||||
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
|
||||
desc.BlendState.RenderTarget[0].SrcBlend = D3D12_BLEND_ONE;
|
||||
desc.BlendState.RenderTarget[0].DestBlend = D3D12_BLEND_ONE;
|
||||
desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
|
||||
desc.InputLayout.pInputElementDescs = inputElementDesc;
|
||||
desc.InputLayout.NumElements = countof(inputElementDesc);
|
||||
|
||||
if (!d3d_compile(ribbon, sizeof(ribbon), NULL, "VSMain", "vs_5_0", &vs_code))
|
||||
goto error;
|
||||
if (!d3d_compile(ribbon, sizeof(ribbon), NULL, "PSMain", "ps_5_0", &ps_code))
|
||||
goto error;
|
||||
|
||||
if (!d3d12_init_pipeline(
|
||||
d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pipes[VIDEO_SHADER_MENU]))
|
||||
goto error;
|
||||
|
||||
Release(vs_code);
|
||||
Release(ps_code);
|
||||
vs_code = NULL;
|
||||
ps_code = NULL;
|
||||
|
||||
if (!d3d_compile(ribbon_simple, sizeof(ribbon_simple), NULL, "VSMain", "vs_5_0", &vs_code))
|
||||
goto error;
|
||||
if (!d3d_compile(ribbon_simple, sizeof(ribbon_simple), NULL, "PSMain", "ps_5_0", &ps_code))
|
||||
goto error;
|
||||
|
||||
if (!d3d12_init_pipeline(
|
||||
d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pipes[VIDEO_SHADER_MENU_2]))
|
||||
goto error;
|
||||
|
||||
Release(vs_code);
|
||||
Release(ps_code);
|
||||
vs_code = NULL;
|
||||
ps_code = NULL;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
Release(vs_code);
|
||||
Release(ps_code);
|
||||
Release(gs_code);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void d3d12_gfx_free(void* data)
|
||||
{
|
||||
unsigned i;
|
||||
d3d12_video_t* d3d12 = (d3d12_video_t*)data;
|
||||
|
||||
font_driver_free_osd();
|
||||
|
||||
Release(d3d12->sprites.vbo);
|
||||
|
||||
Release(d3d12->frame.ubo);
|
||||
Release(d3d12->frame.vbo);
|
||||
Release(d3d12->frame.texture.handle);
|
||||
Release(d3d12->frame.texture.upload_buffer);
|
||||
Release(d3d12->menu.vbo);
|
||||
Release(d3d12->menu.texture.handle);
|
||||
Release(d3d12->menu.texture.upload_buffer);
|
||||
|
||||
free(d3d12->desc.sampler_heap.map);
|
||||
free(d3d12->desc.srv_heap.map);
|
||||
free(d3d12->desc.rtv_heap.map);
|
||||
Release(d3d12->desc.sampler_heap.handle);
|
||||
Release(d3d12->desc.srv_heap.handle);
|
||||
Release(d3d12->desc.rtv_heap.handle);
|
||||
|
||||
Release(d3d12->desc.sl_rootSignature);
|
||||
Release(d3d12->desc.rootSignature);
|
||||
|
||||
Release(d3d12->ubo);
|
||||
|
||||
for (i = 0; i < GFX_MAX_SHADERS; i++)
|
||||
Release(d3d12->pipes[i]);
|
||||
|
||||
Release(d3d12->sprites.pipe);
|
||||
Release(d3d12->sprites.pipe_font);
|
||||
|
||||
Release(d3d12->queue.fence);
|
||||
Release(d3d12->chain.renderTargets[0]);
|
||||
Release(d3d12->chain.renderTargets[1]);
|
||||
Release(d3d12->chain.handle);
|
||||
|
||||
Release(d3d12->queue.cmd);
|
||||
Release(d3d12->queue.allocator);
|
||||
Release(d3d12->queue.handle);
|
||||
|
||||
Release(d3d12->factory);
|
||||
Release(d3d12->device);
|
||||
Release(d3d12->adapter);
|
||||
|
||||
win32_monitor_from_window();
|
||||
win32_destroy_window();
|
||||
|
||||
free(d3d12);
|
||||
}
|
||||
|
||||
static void*
|
||||
d3d12_gfx_init(const video_info_t* video, const input_driver_t** input, void** input_data)
|
||||
{
|
||||
WNDCLASSEX wndclass = { 0 };
|
||||
settings_t* settings = config_get_ptr();
|
||||
d3d12_video_t* d3d12 = (d3d12_video_t*)calloc(1, sizeof(*d3d12));
|
||||
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));
|
||||
|
||||
if (!d3d12)
|
||||
return NULL;
|
||||
@ -95,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;
|
||||
@ -109,36 +423,41 @@ d3d12_gfx_init(const video_info_t* video, const input_driver_t** input, void** i
|
||||
if (!d3d12_init_descriptors(d3d12))
|
||||
goto error;
|
||||
|
||||
if (!d3d12_init_pipeline(d3d12))
|
||||
if (!d3d12_gfx_init_pipelines(d3d12))
|
||||
goto error;
|
||||
|
||||
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);
|
||||
d3d12_set_filtering(d3d12, 0, video->smooth);
|
||||
|
||||
d3d12_create_fullscreen_quad_vbo(d3d12->device, &d3d12->frame.vbo_view, &d3d12->frame.vbo);
|
||||
d3d12_create_fullscreen_quad_vbo(d3d12->device, &d3d12->menu.vbo_view, &d3d12->menu.vbo);
|
||||
|
||||
d3d12_set_filtering(d3d12, 0, video->smooth);
|
||||
d3d12->sprites.capacity = 4096;
|
||||
d3d12->sprites.vbo_view.SizeInBytes = sizeof(d3d12_sprite_t) * d3d12->sprites.capacity;
|
||||
d3d12->sprites.vbo_view.StrideInBytes = sizeof(d3d12_sprite_t);
|
||||
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_get_closest_match_texture2D(d3d12->device, 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_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);
|
||||
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 };
|
||||
@ -148,15 +467,22 @@ 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);
|
||||
|
||||
return d3d12;
|
||||
|
||||
error:
|
||||
RARCH_ERR("[D3D12]: failed to init video driver.\n");
|
||||
free(d3d12);
|
||||
d3d12_gfx_free(d3d12);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -179,7 +505,7 @@ static bool d3d12_gfx_frame(
|
||||
for (i = 0; i < countof(d3d12->chain.renderTargets); i++)
|
||||
Release(d3d12->chain.renderTargets[i]);
|
||||
|
||||
DXGIResizeBuffers(d3d12->chain.handle, 0, 0, 0, (DXGI_FORMAT)0, 0);
|
||||
DXGIResizeBuffers(d3d12->chain.handle, 0, 0, 0, DXGI_FORMAT_UNKNOWN, 0);
|
||||
|
||||
for (i = 0; i < countof(d3d12->chain.renderTargets); i++)
|
||||
{
|
||||
@ -189,18 +515,29 @@ 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();
|
||||
D3D12ResetCommandAllocator(d3d12->queue.allocator);
|
||||
|
||||
D3D12ResetGraphicsCommandList(d3d12->queue.cmd, d3d12->queue.allocator, d3d12->pipe.handle);
|
||||
D3D12SetGraphicsRootSignature(d3d12->queue.cmd, d3d12->pipe.rootSignature);
|
||||
D3D12ResetGraphicsCommandList(
|
||||
d3d12->queue.cmd, d3d12->queue.allocator, d3d12->pipes[VIDEO_SHADER_STOCK_BLEND]);
|
||||
D3D12SetGraphicsRootSignature(d3d12->queue.cmd, d3d12->desc.rootSignature);
|
||||
{
|
||||
D3D12DescriptorHeap desc_heaps[] = { d3d12->pipe.srv_heap.handle,
|
||||
d3d12->pipe.sampler_heap.handle };
|
||||
D3D12DescriptorHeap desc_heaps[] = { d3d12->desc.srv_heap.handle,
|
||||
d3d12->desc.sampler_heap.handle };
|
||||
D3D12SetDescriptorHeaps(d3d12->queue.cmd, countof(desc_heaps), desc_heaps);
|
||||
}
|
||||
|
||||
@ -221,9 +558,8 @@ static bool d3d12_gfx_frame(
|
||||
{
|
||||
d3d12->frame.texture.desc.Width = width;
|
||||
d3d12->frame.texture.desc.Height = height;
|
||||
d3d12_init_texture(
|
||||
d3d12->device, &d3d12->pipe.srv_heap, SRV_HEAP_SLOT_FRAME_TEXTURE,
|
||||
&d3d12->frame.texture);
|
||||
d3d12->frame.texture.srv_heap = &d3d12->desc.srv_heap;
|
||||
d3d12_init_texture(d3d12->device, &d3d12->frame.texture);
|
||||
}
|
||||
d3d12_update_texture(width, height, pitch, d3d12->format, frame, &d3d12->frame.texture);
|
||||
|
||||
@ -232,7 +568,7 @@ static bool d3d12_gfx_frame(
|
||||
#if 0 /* custom viewport doesn't call apply_state_changes, so we can't rely on this for now */
|
||||
if (d3d12->resize_viewport)
|
||||
#endif
|
||||
d3d12_update_viewport(d3d12, false);
|
||||
d3d12_update_viewport(d3d12, false);
|
||||
|
||||
D3D12RSSetViewports(d3d12->queue.cmd, 1, &d3d12->frame.viewport);
|
||||
D3D12RSSetScissorRects(d3d12->queue.cmd, 1, &d3d12->frame.scissorRect);
|
||||
@ -240,7 +576,7 @@ static bool d3d12_gfx_frame(
|
||||
D3D12SetGraphicsRootConstantBufferView(
|
||||
d3d12->queue.cmd, ROOT_ID_UBO, d3d12->frame.ubo_view.BufferLocation);
|
||||
d3d12_set_texture(d3d12->queue.cmd, &d3d12->frame.texture);
|
||||
d3d12_set_sampler(d3d12->queue.cmd, d3d12->frame.sampler);
|
||||
d3d12_set_sampler(d3d12->queue.cmd, d3d12->samplers[RARCH_FILTER_UNSPEC][RARCH_WRAP_DEFAULT]);
|
||||
D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1, &d3d12->frame.vbo_view);
|
||||
D3D12DrawInstanced(d3d12->queue.cmd, 4, 1, 0, 0);
|
||||
|
||||
@ -258,17 +594,34 @@ static bool d3d12_gfx_frame(
|
||||
D3D12RSSetScissorRects(d3d12->queue.cmd, 1, &d3d12->chain.scissorRect);
|
||||
}
|
||||
|
||||
d3d12_set_texture(d3d12->queue.cmd, &d3d12->menu.texture);
|
||||
d3d12_set_sampler(d3d12->queue.cmd, d3d12->menu.sampler);
|
||||
d3d12_set_texture_and_sampler(d3d12->queue.cmd, &d3d12->menu.texture);
|
||||
D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1, &d3d12->menu.vbo_view);
|
||||
D3D12DrawInstanced(d3d12->queue.cmd, 4, 1, 0, 0);
|
||||
}
|
||||
|
||||
D3D12RSSetViewports(d3d12->queue.cmd, 1, &d3d12->chain.viewport);
|
||||
D3D12RSSetScissorRects(d3d12->queue.cmd, 1, &d3d12->chain.scissorRect);
|
||||
|
||||
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);
|
||||
|
||||
d3d12->sprites.enabled = true;
|
||||
#if 1
|
||||
if (d3d12->menu.enabled)
|
||||
menu_driver_frame(video_info);
|
||||
#endif
|
||||
if (msg && *msg)
|
||||
{
|
||||
font_driver_render_msg(video_info, NULL, msg, NULL);
|
||||
dxgi_update_title(video_info);
|
||||
}
|
||||
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);
|
||||
D3D12CloseGraphicsCommandList(d3d12->queue.cmd);
|
||||
|
||||
D3D12ExecuteGraphicsCommandLists(d3d12->queue.handle, 1, &d3d12->queue.cmd);
|
||||
|
||||
#if 1
|
||||
@ -332,44 +685,6 @@ static bool d3d12_gfx_has_windowed(void* data)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void d3d12_gfx_free(void* data)
|
||||
{
|
||||
d3d12_video_t* d3d12 = (d3d12_video_t*)data;
|
||||
|
||||
Release(d3d12->frame.ubo);
|
||||
Release(d3d12->frame.vbo);
|
||||
Release(d3d12->frame.texture.handle);
|
||||
Release(d3d12->frame.texture.upload_buffer);
|
||||
Release(d3d12->menu.vbo);
|
||||
Release(d3d12->menu.texture.handle);
|
||||
Release(d3d12->menu.texture.upload_buffer);
|
||||
|
||||
Release(d3d12->ubo);
|
||||
Release(d3d12->pipe.sampler_heap.handle);
|
||||
Release(d3d12->pipe.srv_heap.handle);
|
||||
Release(d3d12->pipe.rtv_heap.handle);
|
||||
Release(d3d12->pipe.rootSignature);
|
||||
Release(d3d12->pipe.handle);
|
||||
|
||||
Release(d3d12->queue.fence);
|
||||
Release(d3d12->chain.renderTargets[0]);
|
||||
Release(d3d12->chain.renderTargets[1]);
|
||||
Release(d3d12->chain.handle);
|
||||
|
||||
Release(d3d12->queue.cmd);
|
||||
Release(d3d12->queue.allocator);
|
||||
Release(d3d12->queue.handle);
|
||||
|
||||
Release(d3d12->factory);
|
||||
Release(d3d12->device);
|
||||
Release(d3d12->adapter);
|
||||
|
||||
win32_monitor_from_window();
|
||||
win32_destroy_window();
|
||||
|
||||
free(d3d12);
|
||||
}
|
||||
|
||||
static bool d3d12_gfx_set_shader(void* data, enum rarch_shader_type type, const char* path)
|
||||
{
|
||||
(void)data;
|
||||
@ -397,17 +712,18 @@ static bool d3d12_gfx_read_viewport(void* data, uint8_t* buffer, bool is_idle)
|
||||
static void d3d12_set_menu_texture_frame(
|
||||
void* data, const void* frame, bool rgb32, unsigned width, unsigned height, float alpha)
|
||||
{
|
||||
d3d12_video_t* d3d12 = (d3d12_video_t*)data;
|
||||
int pitch = width * (rgb32 ? sizeof(uint32_t) : sizeof(uint16_t));
|
||||
DXGI_FORMAT format = rgb32 ? DXGI_FORMAT_B8G8R8A8_UNORM : (DXGI_FORMAT)DXGI_FORMAT_EX_A4R4G4B4_UNORM;
|
||||
d3d12_video_t* d3d12 = (d3d12_video_t*)data;
|
||||
int pitch = width * (rgb32 ? sizeof(uint32_t) : sizeof(uint16_t));
|
||||
DXGI_FORMAT format =
|
||||
rgb32 ? DXGI_FORMAT_B8G8R8A8_UNORM : (DXGI_FORMAT)DXGI_FORMAT_EX_A4R4G4B4_UNORM;
|
||||
|
||||
if (d3d12->menu.texture.desc.Width != width || d3d12->menu.texture.desc.Height != height)
|
||||
{
|
||||
d3d12->menu.texture.desc.Width = width;
|
||||
d3d12->menu.texture.desc.Height = height;
|
||||
d3d12->menu.texture.desc.Format = d3d12_get_closest_match_texture2D(d3d12->device, format);
|
||||
d3d12_init_texture(
|
||||
d3d12->device, &d3d12->pipe.srv_heap, SRV_HEAP_SLOT_MENU_TEXTURE, &d3d12->menu.texture);
|
||||
d3d12->menu.texture.desc.Format = format;
|
||||
d3d12->menu.texture.srv_heap = &d3d12->desc.srv_heap;
|
||||
d3d12_init_texture(d3d12->device, &d3d12->menu.texture);
|
||||
}
|
||||
|
||||
d3d12_update_texture(width, height, pitch, format, frame, &d3d12->menu.texture);
|
||||
@ -425,8 +741,10 @@ static void d3d12_set_menu_texture_frame(
|
||||
v[3].color[3] = alpha;
|
||||
D3D12Unmap(d3d12->menu.vbo, 0, NULL);
|
||||
}
|
||||
d3d12->menu.sampler = config_get_ptr()->bools.menu_linear_filter ? d3d12->sampler_linear
|
||||
: d3d12->sampler_nearest;
|
||||
|
||||
d3d12->menu.texture.sampler = config_get_ptr()->bools.menu_linear_filter
|
||||
? d3d12->samplers[RARCH_FILTER_LINEAR][RARCH_WRAP_DEFAULT]
|
||||
: d3d12->samplers[RARCH_FILTER_NEAREST][RARCH_WRAP_DEFAULT];
|
||||
}
|
||||
static void d3d12_set_menu_texture_enable(void* data, bool state, bool full_screen)
|
||||
{
|
||||
@ -455,11 +773,78 @@ static void d3d12_gfx_apply_state_changes(void* data)
|
||||
d3d12->resize_viewport = true;
|
||||
}
|
||||
|
||||
static void d3d12_gfx_set_osd_msg(
|
||||
void* data, video_frame_info_t* video_info, const char* msg, const void* params, void* font)
|
||||
{
|
||||
d3d12_video_t* d3d12 = (d3d12_video_t*)data;
|
||||
|
||||
if (d3d12)
|
||||
{
|
||||
if (d3d12->sprites.enabled)
|
||||
font_driver_render_msg(video_info, font, msg, params);
|
||||
else
|
||||
printf("OSD msg: %s\n", 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 */
|
||||
@ -471,7 +856,7 @@ static const video_poke_interface_t d3d12_poke_interface = {
|
||||
d3d12_gfx_apply_state_changes,
|
||||
d3d12_set_menu_texture_frame,
|
||||
d3d12_set_menu_texture_enable,
|
||||
NULL, /* set_osd_msg */
|
||||
d3d12_gfx_set_osd_msg,
|
||||
NULL, /* show_mouse */
|
||||
NULL, /* grab_mouse_toggle */
|
||||
NULL, /* get_current_shader */
|
||||
|
374
gfx/drivers_font/d3d12_font.c
Normal file
374
gfx/drivers_font/d3d12_font.c
Normal file
@ -0,0 +1,374 @@
|
||||
/* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define CINTERFACE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <math.h>
|
||||
#include <encodings/utf.h>
|
||||
|
||||
#include "../font_driver.h"
|
||||
#include "../video_driver.h"
|
||||
#include "../common/d3d12_common.h"
|
||||
|
||||
#include "../../verbosity.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
d3d12_texture_t texture;
|
||||
const font_renderer_driver_t* font_driver;
|
||||
void* font_data;
|
||||
struct font_atlas* atlas;
|
||||
} d3d12_font_t;
|
||||
|
||||
static void*
|
||||
d3d12_font_init_font(void* data, const char* font_path, float font_size, bool is_threaded)
|
||||
{
|
||||
d3d12_video_t* d3d12 = (d3d12_video_t*)data;
|
||||
d3d12_font_t* font = (d3d12_font_t*)calloc(1, sizeof(*font));
|
||||
|
||||
if (!font)
|
||||
return NULL;
|
||||
|
||||
if (!font_renderer_create_default(
|
||||
(const void**)&font->font_driver, &font->font_data, font_path, font_size))
|
||||
{
|
||||
RARCH_WARN("Couldn't initialize font renderer.\n");
|
||||
free(font);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
font->atlas = font->font_driver->get_atlas(font->font_data);
|
||||
font->texture.sampler = d3d12->samplers[RARCH_FILTER_LINEAR][RARCH_WRAP_BORDER];
|
||||
font->texture.desc.Width = font->atlas->width;
|
||||
font->texture.desc.Height = font->atlas->height;
|
||||
font->texture.desc.Format = DXGI_FORMAT_A8_UNORM;
|
||||
font->texture.srv_heap = &d3d12->desc.srv_heap;
|
||||
d3d12_init_texture(d3d12->device, &font->texture);
|
||||
d3d12_update_texture(
|
||||
font->atlas->width, font->atlas->height, font->atlas->width, DXGI_FORMAT_A8_UNORM,
|
||||
font->atlas->buffer, &font->texture);
|
||||
font->atlas->dirty = false;
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
static void d3d12_font_free_font(void* data, bool is_threaded)
|
||||
{
|
||||
d3d12_font_t* font = (d3d12_font_t*)data;
|
||||
|
||||
if (!font)
|
||||
return;
|
||||
|
||||
if (font->font_driver && font->font_data && font->font_driver->free)
|
||||
font->font_driver->free(font->font_data);
|
||||
|
||||
d3d12_release_texture(&font->texture);
|
||||
|
||||
free(font);
|
||||
}
|
||||
|
||||
static int d3d12_font_get_message_width(void* data, const char* msg, unsigned msg_len, float scale)
|
||||
{
|
||||
d3d12_font_t* font = (d3d12_font_t*)data;
|
||||
|
||||
unsigned i;
|
||||
int delta_x = 0;
|
||||
|
||||
if (!font)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < msg_len; i++)
|
||||
{
|
||||
const struct font_glyph* glyph;
|
||||
const char* msg_tmp = &msg[i];
|
||||
unsigned code = utf8_walk(&msg_tmp);
|
||||
unsigned skip = msg_tmp - &msg[i];
|
||||
|
||||
if (skip > 1)
|
||||
i += skip - 1;
|
||||
|
||||
glyph = font->font_driver->get_glyph(font->font_data, code);
|
||||
|
||||
if (!glyph) /* Do something smarter here ... */
|
||||
glyph = font->font_driver->get_glyph(font->font_data, '?');
|
||||
|
||||
if (!glyph)
|
||||
continue;
|
||||
|
||||
delta_x += glyph->advance_x;
|
||||
}
|
||||
|
||||
return delta_x * scale;
|
||||
}
|
||||
|
||||
static void d3d12_font_render_line(
|
||||
video_frame_info_t* video_info,
|
||||
d3d12_font_t* font,
|
||||
const char* msg,
|
||||
unsigned msg_len,
|
||||
float scale,
|
||||
const unsigned int color,
|
||||
float pos_x,
|
||||
float pos_y,
|
||||
unsigned text_align)
|
||||
{
|
||||
unsigned i, count;
|
||||
void* mapped_vbo;
|
||||
d3d12_sprite_t* v;
|
||||
d3d12_sprite_t* vbo_start;
|
||||
d3d12_video_t* d3d12 = (d3d12_video_t*)video_driver_get_ptr(false);
|
||||
unsigned width = video_info->width;
|
||||
unsigned height = video_info->height;
|
||||
int x = roundf(pos_x * width);
|
||||
int y = roundf((1.0 - pos_y) * height);
|
||||
D3D12_RANGE range = { 0, 0 };
|
||||
|
||||
if (!d3d12->sprites.enabled || msg_len > (unsigned)d3d12->sprites.capacity)
|
||||
return;
|
||||
|
||||
if (d3d12->sprites.offset + msg_len > (unsigned)d3d12->sprites.capacity)
|
||||
d3d12->sprites.offset = 0;
|
||||
|
||||
switch (text_align)
|
||||
{
|
||||
case TEXT_ALIGN_RIGHT:
|
||||
x -= d3d12_font_get_message_width(font, msg, msg_len, scale);
|
||||
break;
|
||||
|
||||
case TEXT_ALIGN_CENTER:
|
||||
x -= d3d12_font_get_message_width(font, msg, msg_len, scale) / 2;
|
||||
break;
|
||||
}
|
||||
|
||||
D3D12Map(d3d12->sprites.vbo, 0, &range, (void**)&vbo_start);
|
||||
|
||||
v = vbo_start + d3d12->sprites.offset;
|
||||
range.Begin = (uintptr_t)v - (uintptr_t)vbo_start;
|
||||
|
||||
for (i = 0; i < msg_len; i++)
|
||||
{
|
||||
const struct font_glyph* glyph;
|
||||
const char* msg_tmp = &msg[i];
|
||||
unsigned code = utf8_walk(&msg_tmp);
|
||||
unsigned skip = msg_tmp - &msg[i];
|
||||
|
||||
if (skip > 1)
|
||||
i += skip - 1;
|
||||
|
||||
glyph = font->font_driver->get_glyph(font->font_data, code);
|
||||
|
||||
if (!glyph) /* Do something smarter here ... */
|
||||
glyph = font->font_driver->get_glyph(font->font_data, '?');
|
||||
|
||||
if (!glyph)
|
||||
continue;
|
||||
|
||||
v->pos.x = (x + glyph->draw_offset_x) * scale / (float)d3d12->chain.viewport.Width;
|
||||
v->pos.y = (y + glyph->draw_offset_y) * scale / (float)d3d12->chain.viewport.Height;
|
||||
v->pos.w = glyph->width * scale / (float)d3d12->chain.viewport.Width;
|
||||
v->pos.h = glyph->height * scale / (float)d3d12->chain.viewport.Height;
|
||||
|
||||
v->coords.u = glyph->atlas_offset_x / (float)font->texture.desc.Width;
|
||||
v->coords.v = glyph->atlas_offset_y / (float)font->texture.desc.Height;
|
||||
v->coords.w = glyph->width / (float)font->texture.desc.Width;
|
||||
v->coords.h = glyph->height / (float)font->texture.desc.Height;
|
||||
|
||||
v->params.scaling = 1;
|
||||
v->params.rotation = 0;
|
||||
|
||||
v->colors[0] = color;
|
||||
v->colors[1] = color;
|
||||
v->colors[2] = color;
|
||||
v->colors[3] = color;
|
||||
|
||||
v++;
|
||||
|
||||
x += glyph->advance_x * scale;
|
||||
y += glyph->advance_y * scale;
|
||||
}
|
||||
|
||||
range.End = (uintptr_t)v - (uintptr_t)vbo_start;
|
||||
D3D12Unmap(d3d12->sprites.vbo, 0, &range);
|
||||
|
||||
count = v - vbo_start - d3d12->sprites.offset;
|
||||
|
||||
if (!count)
|
||||
return;
|
||||
|
||||
if (font->atlas->dirty)
|
||||
{
|
||||
d3d12_update_texture(
|
||||
font->atlas->width, font->atlas->height, font->atlas->width, DXGI_FORMAT_A8_UNORM,
|
||||
font->atlas->buffer, &font->texture);
|
||||
font->atlas->dirty = false;
|
||||
}
|
||||
|
||||
if(font->texture.dirty)
|
||||
d3d12_upload_texture(d3d12->queue.cmd, &font->texture);
|
||||
|
||||
D3D12SetPipelineState(d3d12->queue.cmd, d3d12->sprites.pipe_font);
|
||||
d3d12_set_texture_and_sampler(d3d12->queue.cmd, &font->texture);
|
||||
D3D12DrawInstanced(d3d12->queue.cmd, count, 1, d3d12->sprites.offset, 0);
|
||||
|
||||
D3D12SetPipelineState(d3d12->queue.cmd, d3d12->sprites.pipe);
|
||||
|
||||
d3d12->sprites.offset += count;
|
||||
}
|
||||
|
||||
static void d3d12_font_render_message(
|
||||
video_frame_info_t* video_info,
|
||||
d3d12_font_t* font,
|
||||
const char* msg,
|
||||
float scale,
|
||||
const unsigned int color,
|
||||
float pos_x,
|
||||
float pos_y,
|
||||
unsigned text_align)
|
||||
{
|
||||
int lines = 0;
|
||||
float line_height;
|
||||
|
||||
if (!msg || !*msg)
|
||||
return;
|
||||
|
||||
/* If the font height is not supported just draw as usual */
|
||||
if (!font->font_driver->get_line_height)
|
||||
{
|
||||
d3d12_font_render_line(
|
||||
video_info, font, msg, strlen(msg), scale, color, pos_x, pos_y, text_align);
|
||||
return;
|
||||
}
|
||||
|
||||
line_height = font->font_driver->get_line_height(font->font_data) * scale / video_info->height;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
const char* delim = strchr(msg, '\n');
|
||||
|
||||
/* Draw the line */
|
||||
if (delim)
|
||||
{
|
||||
unsigned msg_len = delim - msg;
|
||||
d3d12_font_render_line(
|
||||
video_info, font, msg, msg_len, scale, color, pos_x,
|
||||
pos_y - (float)lines * line_height, text_align);
|
||||
msg += msg_len + 1;
|
||||
lines++;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned msg_len = strlen(msg);
|
||||
d3d12_font_render_line(
|
||||
video_info, font, msg, msg_len, scale, color, pos_x,
|
||||
pos_y - (float)lines * line_height, text_align);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void d3d12_font_render_msg(
|
||||
video_frame_info_t* video_info, void* data, const char* msg, const void* userdata)
|
||||
{
|
||||
float x, y, scale, drop_mod, drop_alpha;
|
||||
int drop_x, drop_y;
|
||||
enum text_alignment text_align;
|
||||
unsigned color, color_dark, r, g, b, alpha, r_dark, g_dark, b_dark, alpha_dark;
|
||||
d3d12_font_t* font = (d3d12_font_t*)data;
|
||||
const struct font_params* params = (const struct font_params*)userdata;
|
||||
unsigned width = video_info->width;
|
||||
unsigned height = video_info->height;
|
||||
|
||||
if (!font || !msg || !*msg)
|
||||
return;
|
||||
|
||||
if (params)
|
||||
{
|
||||
x = params->x;
|
||||
y = params->y;
|
||||
scale = params->scale;
|
||||
text_align = params->text_align;
|
||||
drop_x = params->drop_x;
|
||||
drop_y = params->drop_y;
|
||||
drop_mod = params->drop_mod;
|
||||
drop_alpha = params->drop_alpha;
|
||||
r = FONT_COLOR_GET_RED(params->color);
|
||||
g = FONT_COLOR_GET_GREEN(params->color);
|
||||
b = FONT_COLOR_GET_BLUE(params->color);
|
||||
alpha = FONT_COLOR_GET_ALPHA(params->color);
|
||||
color = DXGI_COLOR_RGBA(r, g, b, alpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
x = video_info->font_msg_pos_x;
|
||||
y = video_info->font_msg_pos_y;
|
||||
scale = 1.0f;
|
||||
text_align = TEXT_ALIGN_LEFT;
|
||||
|
||||
r = (video_info->font_msg_color_r * 255);
|
||||
g = (video_info->font_msg_color_g * 255);
|
||||
b = (video_info->font_msg_color_b * 255);
|
||||
alpha = 255;
|
||||
color = DXGI_COLOR_RGBA(r, g, b, alpha);
|
||||
|
||||
drop_x = -2;
|
||||
drop_y = -2;
|
||||
drop_mod = 0.3f;
|
||||
drop_alpha = 1.0f;
|
||||
}
|
||||
|
||||
if (drop_x || drop_y)
|
||||
{
|
||||
r_dark = r * drop_mod;
|
||||
g_dark = g * drop_mod;
|
||||
b_dark = b * drop_mod;
|
||||
alpha_dark = alpha * drop_alpha;
|
||||
color_dark = DXGI_COLOR_RGBA(r_dark, g_dark, b_dark, alpha_dark);
|
||||
|
||||
d3d12_font_render_message(
|
||||
video_info, font, msg, scale, color_dark, x + scale * drop_x / width,
|
||||
y + scale * drop_y / height, text_align);
|
||||
}
|
||||
|
||||
d3d12_font_render_message(video_info, font, msg, scale, color, x, y, text_align);
|
||||
}
|
||||
|
||||
static const struct font_glyph* d3d12_font_get_glyph(void* data, uint32_t code)
|
||||
{
|
||||
d3d12_font_t* font = (d3d12_font_t*)data;
|
||||
|
||||
if (!font || !font->font_driver)
|
||||
return NULL;
|
||||
|
||||
if (!font->font_driver->ident)
|
||||
return NULL;
|
||||
|
||||
return font->font_driver->get_glyph((void*)font->font_driver, code);
|
||||
}
|
||||
|
||||
static void d3d12_font_bind_block(void* data, void* userdata) { (void)data; }
|
||||
|
||||
font_renderer_t d3d12_font = {
|
||||
d3d12_font_init_font,
|
||||
d3d12_font_free_font,
|
||||
d3d12_font_render_msg,
|
||||
"d3d12font",
|
||||
d3d12_font_get_glyph,
|
||||
d3d12_font_bind_block,
|
||||
NULL, /* flush */
|
||||
d3d12_font_get_message_width,
|
||||
};
|
@ -309,6 +309,37 @@ static bool d3d11_font_init_first(
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_D3D12
|
||||
static const font_renderer_t *d3d12_font_backends[] = {
|
||||
&d3d12_font,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static bool d3d12_font_init_first(
|
||||
const void **font_driver, void **font_handle,
|
||||
void *video_data, const char *font_path,
|
||||
float font_size, bool is_threaded)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; d3d12_font_backends[i]; i++)
|
||||
{
|
||||
void *data = d3d12_font_backends[i]->init(video_data,
|
||||
font_path, font_size,
|
||||
is_threaded);
|
||||
|
||||
if (!data)
|
||||
continue;
|
||||
|
||||
*font_driver = d3d12_font_backends[i];
|
||||
*font_handle = data;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_VITA2D
|
||||
static const font_renderer_t *vita2d_font_backends[] = {
|
||||
&vita2d_vita_font
|
||||
@ -430,6 +461,11 @@ static bool font_init_first(
|
||||
return d3d11_font_init_first(font_driver, font_handle,
|
||||
video_data, font_path, font_size, is_threaded);
|
||||
#endif
|
||||
#ifdef HAVE_D3D12
|
||||
case FONT_DRIVER_RENDER_D3D12_API:
|
||||
return d3d12_font_init_first(font_driver, font_handle,
|
||||
video_data, font_path, font_size, is_threaded);
|
||||
#endif
|
||||
#ifdef HAVE_VITA2D
|
||||
case FONT_DRIVER_RENDER_VITA2D:
|
||||
return vita2d_font_init_first(font_driver, font_handle,
|
||||
|
@ -32,6 +32,7 @@ enum font_driver_render_api
|
||||
FONT_DRIVER_RENDER_OPENGL_API,
|
||||
FONT_DRIVER_RENDER_DIRECT3D_API,
|
||||
FONT_DRIVER_RENDER_D3D11_API,
|
||||
FONT_DRIVER_RENDER_D3D12_API,
|
||||
FONT_DRIVER_RENDER_VITA2D,
|
||||
FONT_DRIVER_RENDER_CTR,
|
||||
FONT_DRIVER_RENDER_WIIU,
|
||||
@ -186,6 +187,7 @@ extern font_renderer_t ctr_font;
|
||||
extern font_renderer_t wiiu_font;
|
||||
extern font_renderer_t vulkan_raster_font;
|
||||
extern font_renderer_t d3d11_font;
|
||||
extern font_renderer_t d3d12_font;
|
||||
extern font_renderer_t caca_font;
|
||||
extern font_renderer_t gdi_font;
|
||||
extern font_renderer_t vga_font;
|
||||
|
@ -517,6 +517,10 @@ FONTS
|
||||
#include "../gfx/drivers_font/d3d11_font.c"
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_D3D12)
|
||||
#include "../gfx/drivers_font/d3d12_font.c"
|
||||
#endif
|
||||
|
||||
/*============================================================
|
||||
INPUT
|
||||
============================================================ */
|
||||
@ -1168,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
|
||||
|
244
menu/drivers_display/menu_display_d3d12.c
Normal file
244
menu/drivers_display/menu_display_d3d12.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define CINTERFACE
|
||||
|
||||
#include <retro_miscellaneous.h>
|
||||
|
||||
#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",
|
||||
};
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user