From 05797eb6b80196c35e8ad721f11ff5245b96a086 Mon Sep 17 00:00:00 2001 From: libretroadmin Date: Sat, 4 Jun 2022 06:02:50 +0200 Subject: [PATCH] (D3D12) Move functions over to files that need it --- gfx/common/d3d12_common.c | 665 +++----------------------------------- gfx/common/d3d12_common.h | 25 +- gfx/drivers/d3d12.c | 645 +++++++++++++++++++++++++++++++++--- 3 files changed, 648 insertions(+), 687 deletions(-) diff --git a/gfx/common/d3d12_common.c b/gfx/common/d3d12_common.c index 0ca66de9e8..f91f1ba530 100644 --- a/gfx/common/d3d12_common.c +++ b/gfx/common/d3d12_common.c @@ -139,302 +139,6 @@ HRESULT WINAPI D3D12SerializeVersionedRootSignature( } #endif -bool d3d12_init_base(d3d12_video_t* d3d12) -{ - DXGIAdapter adapter = NULL; -#ifdef DEBUG -#ifdef __WINRT__ - if (SUCCEEDED(D3D12GetDebugInterface_(&d3d12->debugController))) - d3d12->debugController->lpVtbl->EnableDebugLayer(&d3d12->debugController); -#else - if (SUCCEEDED(D3D12GetDebugInterface_(&d3d12->debugController))) - d3d12->debugController->lpVtbl->EnableDebugLayer(d3d12->debugController); -#endif -#endif - -#ifdef __WINRT__ - DXGICreateFactory2(&d3d12->factory); -#else - DXGICreateFactory(&d3d12->factory); -#endif - { - int i = 0; - settings_t *settings = config_get_ptr(); - int gpu_index = settings->ints.d3d12_gpu_index; - - if (d3d12->gpu_list) - string_list_free(d3d12->gpu_list); - - d3d12->gpu_list = string_list_new(); - - for (;;) - { - char str[128]; - union string_list_elem_attr attr = {0}; - DXGI_ADAPTER_DESC desc = {0}; - - str[0] = '\0'; - -#ifdef __WINRT__ - if (FAILED(DXGIEnumAdapters2(d3d12->factory, i, &adapter))) - break; -#else - if (FAILED(DXGIEnumAdapters(d3d12->factory, i, &adapter))) - break; -#endif - IDXGIAdapter_GetDesc(adapter, &desc); - - utf16_to_char_string((const uint16_t*)desc.Description, str, sizeof(str)); - - RARCH_LOG("[D3D12]: Found GPU at index %d: \"%s\".\n", i, str); - - string_list_append(d3d12->gpu_list, str, attr); - - if (i < D3D12_MAX_GPU_COUNT) - { - AddRef(adapter); - d3d12->adapters[i] = adapter; - } - Release(adapter); - adapter = NULL; - - i++; - if (i >= D3D12_MAX_GPU_COUNT) - break; - } - - video_driver_set_gpu_api_devices(GFX_CTX_DIRECT3D12_API, d3d12->gpu_list); - - if (0 <= gpu_index && gpu_index <= i && gpu_index < D3D12_MAX_GPU_COUNT) - { - d3d12->adapter = d3d12->adapters[gpu_index]; - AddRef(d3d12->adapter); - RARCH_LOG("[D3D12]: Using GPU index %d.\n", gpu_index); - video_driver_set_gpu_device_string( - d3d12->gpu_list->elems[gpu_index].data); - } - else - { - RARCH_WARN("[D3D12]: Invalid GPU index %d, using first device found.\n", gpu_index); - d3d12->adapter = d3d12->adapters[0]; - AddRef(d3d12->adapter); - } - - if (!SUCCEEDED(D3D12CreateDevice_(d3d12->adapter, D3D_FEATURE_LEVEL_11_0, &d3d12->device))) - RARCH_WARN("[D3D12]: Could not create D3D12 device.\n"); - } - - return true; -} - -bool d3d12_init_queue(d3d12_video_t* d3d12) -{ - { - static const D3D12_COMMAND_QUEUE_DESC desc = { - D3D12_COMMAND_LIST_TYPE_DIRECT, - 0, - D3D12_COMMAND_QUEUE_FLAG_NONE, - 0 - }; - D3D12CreateCommandQueue( - d3d12->device, - (D3D12_COMMAND_QUEUE_DESC*)&desc, - &d3d12->queue.handle); - } - - D3D12CreateCommandAllocator( - d3d12->device, - D3D12_COMMAND_LIST_TYPE_DIRECT, - &d3d12->queue.allocator); - - D3D12CreateGraphicsCommandList( - d3d12->device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT, d3d12->queue.allocator, - d3d12->pipes[VIDEO_SHADER_STOCK_BLEND], &d3d12->queue.cmd); - - D3D12CloseGraphicsCommandList(d3d12->queue.cmd); - - D3D12CreateFence(d3d12->device, 0, D3D12_FENCE_FLAG_NONE, &d3d12->queue.fence); - d3d12->queue.fenceValue = 0; - d3d12->queue.fenceEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - - return true; -} - -bool d3d12_init_swapchain(d3d12_video_t* d3d12, - int width, int height, void* corewindow) -{ - unsigned i; - HRESULT hr; - HWND hwnd = (HWND)corewindow; -#ifdef __WINRT__ - DXGI_SWAP_CHAIN_DESC1 desc = {{0}}; -#else - DXGI_SWAP_CHAIN_DESC desc = {{0}}; -#endif -#ifdef HAVE_DXGI_HDR - DXGI_COLOR_SPACE_TYPE color_space; -#endif - -#ifdef HAVE_DXGI_HDR - d3d12->chain.formats[DXGI_SWAPCHAIN_BIT_DEPTH_8] = DXGI_FORMAT_R8G8B8A8_UNORM; - d3d12->chain.formats[DXGI_SWAPCHAIN_BIT_DEPTH_10] = DXGI_FORMAT_R10G10B10A2_UNORM; - d3d12->chain.formats[DXGI_SWAPCHAIN_BIT_DEPTH_16] = DXGI_FORMAT_R16G16B16A16_UNORM; - - if (!(d3d12->hdr.support = - dxgi_check_display_hdr_support(d3d12->factory, hwnd))) - d3d12->hdr.enable = false; - - d3d12->chain.bit_depth = d3d12->hdr.enable - ? DXGI_SWAPCHAIN_BIT_DEPTH_10 - : DXGI_SWAPCHAIN_BIT_DEPTH_8; -#endif - - desc.BufferCount = countof(d3d12->chain.renderTargets); - desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; -#ifdef __WINRT__ - desc.Width = width; - desc.Height = height; -#else - desc.BufferDesc.Width = width; - desc.BufferDesc.Height = height; - desc.BufferDesc.RefreshRate.Numerator = 0; - desc.BufferDesc.RefreshRate.Denominator = 1; -#endif - -#ifdef HAVE_DXGI_HDR -#ifdef __WINRT__ - desc.Format = d3d12->chain.formats[d3d12->chain.bit_depth]; -#else - desc.BufferDesc.Format = d3d12->chain.formats[d3d12->chain.bit_depth]; -#endif -#else -#ifdef __WINRT__ - desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; -#else - desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; -#endif -#endif - - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; -#ifdef HAVE_WINDOW - desc.OutputWindow = hwnd; - desc.Windowed = TRUE; -#endif -#if 0 - desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; -#else - desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; -#endif - desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; - -#ifdef __WINRT__ - hr = DXGICreateSwapChainForCoreWindow(d3d12->factory, d3d12->queue.handle, corewindow, &desc, NULL, &d3d12->chain.handle); -#else - hr = DXGICreateSwapChain(d3d12->factory, d3d12->queue.handle, &desc, &d3d12->chain.handle); -#endif - if (FAILED(hr)) - { - RARCH_ERR("[D3D12]: Failed to create the swap chain (0x%08X)\n", hr); - return false; - } - -#ifdef HAVE_WINDOW - DXGIMakeWindowAssociation(d3d12->factory, hwnd, DXGI_MWA_NO_ALT_ENTER); -#endif - -#ifdef HAVE_DXGI_HDR - /* Check display HDR support and - initialize ST.2084 support to match - the display's support. */ - color_space = - d3d12->hdr.enable - ? DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 - : DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; - - dxgi_swapchain_color_space(d3d12->chain.handle, - &d3d12->chain.color_space, color_space); - dxgi_set_hdr_metadata( - d3d12->chain.handle, - d3d12->hdr.support, - d3d12->chain.bit_depth, - d3d12->chain.color_space, - d3d12->hdr.max_output_nits, - d3d12->hdr.min_output_nits, - d3d12->hdr.max_cll, - d3d12->hdr.max_fall); -#endif - - d3d12->chain.frame_index = DXGIGetCurrentBackBufferIndex(d3d12->chain.handle); - - for (i = 0; i < countof(d3d12->chain.renderTargets); i++) - { - DXGIGetSwapChainBuffer(d3d12->chain.handle, i, &d3d12->chain.renderTargets[i]); - D3D12CreateRenderTargetView( - d3d12->device, d3d12->chain.renderTargets[i], NULL, d3d12->chain.desc_handles[i]); - } - -#ifdef HAVE_DXGI_HDR - memset(&d3d12->chain.back_buffer, - 0, sizeof(d3d12->chain.back_buffer)); - d3d12->chain.back_buffer.desc.Width = width; - d3d12->chain.back_buffer.desc.Height = height; - d3d12->chain.back_buffer.desc.Format = - d3d12->shader_preset && d3d12->shader_preset->passes ? glslang_format_to_dxgi(d3d12->pass[d3d12->shader_preset->passes - 1].semantics.format) : DXGI_FORMAT_R8G8B8A8_UNORM; - d3d12->chain.back_buffer.desc.Flags = - D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; - d3d12->chain.back_buffer.srv_heap = - &d3d12->desc.srv_heap; - d3d12->chain.back_buffer.rt_view.ptr = - d3d12->desc.rtv_heap.cpu.ptr - + (countof(d3d12->chain.renderTargets)) - * d3d12->desc.rtv_heap.stride; - d3d12_init_texture(d3d12->device, &d3d12->chain.back_buffer); -#endif - - d3d12->chain.viewport.Width = width; - d3d12->chain.viewport.Height = height; - d3d12->chain.scissorRect.right = width; - d3d12->chain.scissorRect.bottom = height; - - return true; -} - -static void d3d12_init_descriptor_heap(D3D12Device device, d3d12_descriptor_heap_t* out) -{ - D3D12CreateDescriptorHeap(device, &out->desc, &out->handle); - 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 inline void d3d12_release_descriptor_heap(d3d12_descriptor_heap_t* heap) -{ - free(heap->map); - Release(heap->handle); -} - -static D3D12_CPU_DESCRIPTOR_HANDLE d3d12_descriptor_heap_slot_alloc(d3d12_descriptor_heap_t* heap) -{ - int i; - D3D12_CPU_DESCRIPTOR_HANDLE handle = { 0 }; - - for (i = heap->start; i < (int)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) { @@ -454,285 +158,6 @@ d3d12_descriptor_heap_slot_free(d3d12_descriptor_heap_t* heap, D3D12_CPU_DESCRIP 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) -{ - int i, j; - D3D12_ROOT_SIGNATURE_DESC desc; - D3D12_DESCRIPTOR_RANGE srv_tbl[1] = { { D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1 } }; - D3D12_DESCRIPTOR_RANGE uav_tbl[1] = { { D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1 } }; - D3D12_DESCRIPTOR_RANGE sampler_tbl[1] = { { D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, 1 } }; - D3D12_STATIC_SAMPLER_DESC static_sampler = { D3D12_FILTER_MIN_MAG_MIP_POINT }; - D3D12_ROOT_PARAMETER root_params[ROOT_ID_MAX]; - D3D12_ROOT_PARAMETER cs_root_params[CS_ROOT_ID_MAX]; - - root_params[ROOT_ID_TEXTURE_T].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - root_params[ROOT_ID_TEXTURE_T].DescriptorTable.NumDescriptorRanges = countof(srv_tbl); - root_params[ROOT_ID_TEXTURE_T].DescriptorTable.pDescriptorRanges = srv_tbl; - root_params[ROOT_ID_TEXTURE_T].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; - - root_params[ROOT_ID_SAMPLER_T].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - root_params[ROOT_ID_SAMPLER_T].DescriptorTable.NumDescriptorRanges = countof(sampler_tbl); - root_params[ROOT_ID_SAMPLER_T].DescriptorTable.pDescriptorRanges = sampler_tbl; - root_params[ROOT_ID_SAMPLER_T].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; - - root_params[ROOT_ID_UBO].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; - root_params[ROOT_ID_UBO].Descriptor.RegisterSpace = 0; - root_params[ROOT_ID_UBO].Descriptor.ShaderRegister = 0; - root_params[ROOT_ID_UBO].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; - - root_params[ROOT_ID_PC].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; - root_params[ROOT_ID_PC].Descriptor.RegisterSpace = 0; - root_params[ROOT_ID_PC].Descriptor.ShaderRegister = 1; - root_params[ROOT_ID_PC].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; - - desc.NumParameters = countof(root_params); - desc.pParameters = root_params; - desc.NumStaticSamplers = 0; - desc.pStaticSamplers = NULL; - desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; - - d3d12_create_root_signature(d3d12->device, &desc, &d3d12->desc.rootSignature); - - 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); - - cs_root_params[CS_ROOT_ID_TEXTURE_T].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - cs_root_params[CS_ROOT_ID_TEXTURE_T].DescriptorTable.NumDescriptorRanges = countof(srv_tbl); - cs_root_params[CS_ROOT_ID_TEXTURE_T].DescriptorTable.pDescriptorRanges = srv_tbl; - cs_root_params[CS_ROOT_ID_TEXTURE_T].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; - - cs_root_params[CS_ROOT_ID_UAV_T].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; - cs_root_params[CS_ROOT_ID_UAV_T].DescriptorTable.NumDescriptorRanges = countof(uav_tbl); - cs_root_params[CS_ROOT_ID_UAV_T].DescriptorTable.pDescriptorRanges = uav_tbl; - cs_root_params[CS_ROOT_ID_UAV_T].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; - - cs_root_params[CS_ROOT_ID_CONSTANTS].ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; - cs_root_params[CS_ROOT_ID_CONSTANTS].Constants.Num32BitValues = 3; - cs_root_params[CS_ROOT_ID_CONSTANTS].Constants.RegisterSpace = 0; - cs_root_params[CS_ROOT_ID_CONSTANTS].Constants.ShaderRegister = 0; - cs_root_params[CS_ROOT_ID_CONSTANTS].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; - - static_sampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; - static_sampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; - static_sampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; -#if 0 - static_sampler.MaxAnisotropy = 1; - static_sampler.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; - static_sampler.MinLOD = -D3D12_FLOAT32_MAX; - static_sampler.MaxLOD = D3D12_FLOAT32_MAX; -#endif - - desc.NumParameters = countof(cs_root_params); - desc.pParameters = cs_root_params; - desc.NumStaticSamplers = 1; - desc.pStaticSamplers = &static_sampler; - desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_DENY_VERTEX_SHADER_ROOT_ACCESS | - D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS | - D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS | - D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS | - D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS; - - d3d12_create_root_signature(d3d12->device, &desc, &d3d12->desc.cs_rootSignature); - - d3d12->desc.rtv_heap.desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; - d3d12->desc.rtv_heap.desc.NumDescriptors = countof(d3d12->chain.renderTargets) + GFX_MAX_SHADERS * 2; - d3d12->desc.rtv_heap.desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; - d3d12_init_descriptor_heap(d3d12->device, &d3d12->desc.rtv_heap); - - d3d12->desc.srv_heap.desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; - d3d12->desc.srv_heap.desc.NumDescriptors = SLANG_NUM_BINDINGS * GFX_MAX_SHADERS + 2048; - d3d12->desc.srv_heap.desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; - d3d12_init_descriptor_heap(d3d12->device, &d3d12->desc.srv_heap); - - d3d12->desc.sampler_heap.desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER; - d3d12->desc.sampler_heap.desc.NumDescriptors = - SLANG_NUM_BINDINGS * GFX_MAX_SHADERS + 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); - - for (i = 0; i < countof(d3d12->chain.renderTargets); i++) - { - d3d12->chain.desc_handles[i].ptr = - d3d12->desc.rtv_heap.cpu.ptr + i * d3d12->desc.rtv_heap.stride; - } - - for (i = 0; i < GFX_MAX_SHADERS; i++) - { - d3d12->pass[i].rt.rt_view.ptr = - d3d12->desc.rtv_heap.cpu.ptr + - (countof(d3d12->chain.renderTargets) + (2 * i)) * d3d12->desc.rtv_heap.stride; - d3d12->pass[i].feedback.rt_view.ptr = d3d12->pass[i].rt.rt_view.ptr + d3d12->desc.rtv_heap.stride; - - d3d12->pass[i].textures.ptr = d3d12_descriptor_heap_slot_alloc(&d3d12->desc.srv_heap).ptr - - d3d12->desc.srv_heap.cpu.ptr + d3d12->desc.srv_heap.gpu.ptr; - d3d12->pass[i].samplers.ptr = - d3d12_descriptor_heap_slot_alloc(&d3d12->desc.sampler_heap).ptr - - d3d12->desc.sampler_heap.cpu.ptr + d3d12->desc.sampler_heap.gpu.ptr; - - for (j = 1; j < SLANG_NUM_BINDINGS; j++) - { - d3d12_descriptor_heap_slot_alloc(&d3d12->desc.srv_heap); - d3d12_descriptor_heap_slot_alloc(&d3d12->desc.sampler_heap); - } - } - - return true; -} - -static INLINE D3D12_GPU_DESCRIPTOR_HANDLE - d3d12_create_sampler(D3D12Device device, D3D12_SAMPLER_DESC* desc, d3d12_descriptor_heap_t* heap) -{ - 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 }; - - D3D12CreateSampler(device, desc, cpu_handle); - return gpu_handle; -} - -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++) - { - switch (i) - { - default: - case RARCH_WRAP_BORDER: - desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_BORDER; - break; - - 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, -}; - -D3D12_RENDER_TARGET_BLEND_DESC d3d12_blend_disable_desc = { - FALSE, - 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; - } - - 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; -} - D3D12_GPU_VIRTUAL_ADDRESS d3d12_create_buffer(D3D12Device device, UINT size_in_bytes, D3D12Resource* buffer) { @@ -772,6 +197,49 @@ void d3d12_release_texture(d3d12_texture_t* texture) Release(texture->handle); Release(texture->upload_buffer); } + +D3D12_CPU_DESCRIPTOR_HANDLE d3d12_descriptor_heap_slot_alloc(d3d12_descriptor_heap_t* heap) +{ + int i; + D3D12_CPU_DESCRIPTOR_HANDLE handle = { 0 }; + + for (i = heap->start; i < (int)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 DXGI_FORMAT d3d12_get_closest_match(D3D12Device device, D3D12_FEATURE_DATA_FORMAT_SUPPORT* desired) +{ + DXGI_FORMAT default_list[] = { desired->Format, DXGI_FORMAT_UNKNOWN }; + DXGI_FORMAT* format = dxgi_get_format_fallback_list(desired->Format); + + if (!format) + format = default_list; + + while (*format != DXGI_FORMAT_UNKNOWN) + { + D3D12_FEATURE_DATA_FORMAT_SUPPORT format_support = { *format }; + if (SUCCEEDED(D3D12CheckFeatureSupport( + device, D3D12_FEATURE_FORMAT_SUPPORT, &format_support, sizeof(format_support))) && + ((format_support.Support1 & desired->Support1) == desired->Support1) && + ((format_support.Support2 & desired->Support2) == desired->Support2)) + break; + format++; + } + assert(*format); + return *format; +} + void d3d12_init_texture(D3D12Device device, d3d12_texture_t* texture) { int i; @@ -910,6 +378,7 @@ void d3d12_update_texture( texture->dirty = true; } + void d3d12_upload_texture(D3D12GraphicsCommandList cmd, d3d12_texture_t* texture, void *userdata) { @@ -986,49 +455,3 @@ void d3d12_upload_texture(D3D12GraphicsCommandList cmd, texture->dirty = false; } - -void d3d12_create_fullscreen_quad_vbo( - D3D12Device device, D3D12_VERTEX_BUFFER_VIEW* view, D3D12Resource* vbo) -{ - static const d3d12_vertex_t vertices[] = { - { { 0.0f, 0.0f }, { 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, - { { 0.0f, 1.0f }, { 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, - { { 1.0f, 0.0f }, { 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, - { { 1.0f, 1.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, - }; - - view->SizeInBytes = sizeof(vertices); - view->StrideInBytes = sizeof(*vertices); - view->BufferLocation = d3d12_create_buffer(device, view->SizeInBytes, vbo); - - { - void* vertex_data_begin; - D3D12_RANGE read_range = { 0, 0 }; - - D3D12Map(*vbo, 0, &read_range, &vertex_data_begin); - memcpy(vertex_data_begin, vertices, sizeof(vertices)); - D3D12Unmap(*vbo, 0, NULL); - } -} - -DXGI_FORMAT d3d12_get_closest_match(D3D12Device device, D3D12_FEATURE_DATA_FORMAT_SUPPORT* desired) -{ - DXGI_FORMAT default_list[] = { desired->Format, DXGI_FORMAT_UNKNOWN }; - DXGI_FORMAT* format = dxgi_get_format_fallback_list(desired->Format); - - if (!format) - format = default_list; - - while (*format != DXGI_FORMAT_UNKNOWN) - { - D3D12_FEATURE_DATA_FORMAT_SUPPORT format_support = { *format }; - if (SUCCEEDED(D3D12CheckFeatureSupport( - device, D3D12_FEATURE_FORMAT_SUPPORT, &format_support, sizeof(format_support))) && - ((format_support.Support1 & desired->Support1) == desired->Support1) && - ((format_support.Support2 & desired->Support2) == desired->Support2)) - break; - format++; - } - assert(*format); - return *format; -} diff --git a/gfx/common/d3d12_common.h b/gfx/common/d3d12_common.h index fb74f1f4f5..bc2a8b18ef 100644 --- a/gfx/common/d3d12_common.h +++ b/gfx/common/d3d12_common.h @@ -736,25 +736,7 @@ D3D12GetGPUDescriptorHandleForHeapStart(D3D12DescriptorHeap descriptor_heap) RETRO_BEGIN_DECLS -extern D3D12_RENDER_TARGET_BLEND_DESC d3d12_blend_enable_desc; -extern D3D12_RENDER_TARGET_BLEND_DESC d3d12_blend_disable_desc; - -bool d3d12_init_base(d3d12_video_t* d3d12); - -bool d3d12_init_descriptors(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, void *corewindow); - -bool d3d12_init_queue(d3d12_video_t* d3d12); +D3D12_CPU_DESCRIPTOR_HANDLE d3d12_descriptor_heap_slot_alloc(d3d12_descriptor_heap_t* heap); D3D12_GPU_VIRTUAL_ADDRESS d3d12_create_buffer(D3D12Device device, UINT size_in_bytes, D3D12Resource* buffer); @@ -773,11 +755,6 @@ void d3d12_update_texture( void d3d12_upload_texture(D3D12GraphicsCommandList cmd, d3d12_texture_t* texture, void *userdata); -void d3d12_create_fullscreen_quad_vbo( - D3D12Device device, D3D12_VERTEX_BUFFER_VIEW* view, D3D12Resource* vbo); - -DXGI_FORMAT d3d12_get_closest_match(D3D12Device device, D3D12_FEATURE_DATA_FORMAT_SUPPORT* desired); - #if !defined(__cplusplus) || defined(CINTERFACE) static INLINE void d3d12_resource_transition( D3D12GraphicsCommandList cmd, diff --git a/gfx/drivers/d3d12.c b/gfx/drivers/d3d12.c index 7fdfead119..1d935f2a91 100644 --- a/gfx/drivers/d3d12.c +++ b/gfx/drivers/d3d12.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -64,6 +65,34 @@ #include "../../uwp/uwp_func.h" #endif +static 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, +}; + +static D3D12_RENDER_TARGET_BLEND_DESC d3d12_blend_disable_desc = { + FALSE, + 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, +}; + + + /* Temporary workaround for d3d12 not being able to poll flags during init */ static gfx_ctx_driver_t d3d12_fake_context; static uint32_t d3d12_get_flags(void *data); @@ -511,6 +540,56 @@ static void d3d12_free_shader_preset(d3d12_video_t* d3d12) d3d12->resize_render_targets = false; } +static void 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; + } + + 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); +} + static bool d3d12_gfx_set_shader(void* data, enum rarch_shader_type type, const char* path) { #if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS) @@ -621,8 +700,8 @@ static bool d3d12_gfx_set_shader(void* data, enum rarch_shader_type type, const desc.InputLayout.pInputElementDescs = inputElementDesc; desc.InputLayout.NumElements = countof(inputElementDesc); - if (!d3d12_init_pipeline( - d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pass[i].pipe)) { } + d3d12_init_pipeline( + d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pass[i].pipe); free(d3d12->shader_preset->pass[i].source.string.vertex); free(d3d12->shader_preset->pass[i].source.string.fragment); @@ -765,10 +844,9 @@ static bool d3d12_gfx_init_pipelines(d3d12_video_t* d3d12) desc.InputLayout.pInputElementDescs = inputElementDesc; desc.InputLayout.NumElements = countof(inputElementDesc); - if (!d3d12_init_pipeline( + d3d12_init_pipeline( d3d12->device, vs_code, ps_code, NULL, &desc, - &d3d12->pipes[VIDEO_SHADER_STOCK_HDR])) - goto error; + &d3d12->pipes[VIDEO_SHADER_STOCK_HDR]); Release(vs_code); Release(ps_code); @@ -803,10 +881,9 @@ static bool d3d12_gfx_init_pipelines(d3d12_video_t* d3d12) desc.InputLayout.pInputElementDescs = inputElementDesc; desc.InputLayout.NumElements = countof(inputElementDesc); - if (!d3d12_init_pipeline( + d3d12_init_pipeline( d3d12->device, vs_code, ps_code, NULL, &desc, - &d3d12->pipes[VIDEO_SHADER_STOCK_BLEND])) - goto error; + &d3d12->pipes[VIDEO_SHADER_STOCK_BLEND]); Release(vs_code); Release(ps_code); @@ -847,14 +924,12 @@ static bool d3d12_gfx_init_pipelines(d3d12_video_t* d3d12) 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_noblend)) - goto error; + d3d12_init_pipeline( + d3d12->device, vs_code, ps_code, gs_code, &desc, &d3d12->sprites.pipe_noblend); desc.BlendState.RenderTarget[0].BlendEnable = true; - if (!d3d12_init_pipeline( - d3d12->device, vs_code, ps_code, gs_code, &desc, &d3d12->sprites.pipe_blend)) - goto error; + d3d12_init_pipeline( + d3d12->device, vs_code, ps_code, gs_code, &desc, &d3d12->sprites.pipe_blend); Release(ps_code); ps_code = NULL; @@ -862,9 +937,8 @@ static bool d3d12_gfx_init_pipelines(d3d12_video_t* d3d12) 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; + d3d12_init_pipeline( + d3d12->device, vs_code, ps_code, gs_code, &desc, &d3d12->sprites.pipe_font); Release(vs_code); Release(ps_code); @@ -900,9 +974,8 @@ static bool d3d12_gfx_init_pipelines(d3d12_video_t* d3d12) 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; + d3d12_init_pipeline( + d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pipes[VIDEO_SHADER_MENU]); Release(vs_code); Release(ps_code); @@ -914,9 +987,8 @@ static bool d3d12_gfx_init_pipelines(d3d12_video_t* d3d12) 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; + d3d12_init_pipeline( + d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pipes[VIDEO_SHADER_MENU_2]); Release(vs_code); Release(ps_code); @@ -954,9 +1026,8 @@ static bool d3d12_gfx_init_pipelines(d3d12_video_t* d3d12) 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; + d3d12_init_pipeline( + d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pipes[VIDEO_SHADER_MENU_3]); Release(vs_code); Release(ps_code); @@ -968,9 +1039,8 @@ static bool d3d12_gfx_init_pipelines(d3d12_video_t* d3d12) 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; + d3d12_init_pipeline( + d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pipes[VIDEO_SHADER_MENU_4]); Release(vs_code); Release(ps_code); @@ -982,9 +1052,8 @@ static bool d3d12_gfx_init_pipelines(d3d12_video_t* d3d12) 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; + d3d12_init_pipeline( + d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pipes[VIDEO_SHADER_MENU_5]); Release(vs_code); Release(ps_code); @@ -996,9 +1065,8 @@ static bool d3d12_gfx_init_pipelines(d3d12_video_t* d3d12) 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; + d3d12_init_pipeline( + d3d12->device, vs_code, ps_code, NULL, &desc, &d3d12->pipes[VIDEO_SHADER_MENU_6]); Release(vs_code); Release(ps_code); @@ -1126,6 +1194,503 @@ static void d3d12_gfx_free(void* data) free(d3d12); } +static bool d3d12_init_swapchain(d3d12_video_t* d3d12, + int width, int height, void* corewindow) +{ + unsigned i; + HRESULT hr; + HWND hwnd = (HWND)corewindow; +#ifdef __WINRT__ + DXGI_SWAP_CHAIN_DESC1 desc = {{0}}; +#else + DXGI_SWAP_CHAIN_DESC desc = {{0}}; +#endif +#ifdef HAVE_DXGI_HDR + DXGI_COLOR_SPACE_TYPE color_space; +#endif + +#ifdef HAVE_DXGI_HDR + d3d12->chain.formats[DXGI_SWAPCHAIN_BIT_DEPTH_8] = DXGI_FORMAT_R8G8B8A8_UNORM; + d3d12->chain.formats[DXGI_SWAPCHAIN_BIT_DEPTH_10] = DXGI_FORMAT_R10G10B10A2_UNORM; + d3d12->chain.formats[DXGI_SWAPCHAIN_BIT_DEPTH_16] = DXGI_FORMAT_R16G16B16A16_UNORM; + + if (!(d3d12->hdr.support = + dxgi_check_display_hdr_support(d3d12->factory, hwnd))) + d3d12->hdr.enable = false; + + d3d12->chain.bit_depth = d3d12->hdr.enable + ? DXGI_SWAPCHAIN_BIT_DEPTH_10 + : DXGI_SWAPCHAIN_BIT_DEPTH_8; +#endif + + desc.BufferCount = countof(d3d12->chain.renderTargets); + desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; +#ifdef __WINRT__ + desc.Width = width; + desc.Height = height; +#else + desc.BufferDesc.Width = width; + desc.BufferDesc.Height = height; + desc.BufferDesc.RefreshRate.Numerator = 0; + desc.BufferDesc.RefreshRate.Denominator = 1; +#endif + +#ifdef HAVE_DXGI_HDR +#ifdef __WINRT__ + desc.Format = d3d12->chain.formats[d3d12->chain.bit_depth]; +#else + desc.BufferDesc.Format = d3d12->chain.formats[d3d12->chain.bit_depth]; +#endif +#else +#ifdef __WINRT__ + desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; +#else + desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; +#endif +#endif + + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; +#ifdef HAVE_WINDOW + desc.OutputWindow = hwnd; + desc.Windowed = TRUE; +#endif +#if 0 + desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; +#else + desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; +#endif + desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; + +#ifdef __WINRT__ + hr = DXGICreateSwapChainForCoreWindow(d3d12->factory, d3d12->queue.handle, corewindow, &desc, NULL, &d3d12->chain.handle); +#else + hr = DXGICreateSwapChain(d3d12->factory, d3d12->queue.handle, &desc, &d3d12->chain.handle); +#endif + if (FAILED(hr)) + { + RARCH_ERR("[D3D12]: Failed to create the swap chain (0x%08X)\n", hr); + return false; + } + +#ifdef HAVE_WINDOW + DXGIMakeWindowAssociation(d3d12->factory, hwnd, DXGI_MWA_NO_ALT_ENTER); +#endif + +#ifdef HAVE_DXGI_HDR + /* Check display HDR support and + initialize ST.2084 support to match + the display's support. */ + color_space = + d3d12->hdr.enable + ? DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 + : DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; + + dxgi_swapchain_color_space(d3d12->chain.handle, + &d3d12->chain.color_space, color_space); + dxgi_set_hdr_metadata( + d3d12->chain.handle, + d3d12->hdr.support, + d3d12->chain.bit_depth, + d3d12->chain.color_space, + d3d12->hdr.max_output_nits, + d3d12->hdr.min_output_nits, + d3d12->hdr.max_cll, + d3d12->hdr.max_fall); +#endif + + d3d12->chain.frame_index = DXGIGetCurrentBackBufferIndex(d3d12->chain.handle); + + for (i = 0; i < countof(d3d12->chain.renderTargets); i++) + { + DXGIGetSwapChainBuffer(d3d12->chain.handle, i, &d3d12->chain.renderTargets[i]); + D3D12CreateRenderTargetView( + d3d12->device, d3d12->chain.renderTargets[i], NULL, d3d12->chain.desc_handles[i]); + } + +#ifdef HAVE_DXGI_HDR + memset(&d3d12->chain.back_buffer, + 0, sizeof(d3d12->chain.back_buffer)); + d3d12->chain.back_buffer.desc.Width = width; + d3d12->chain.back_buffer.desc.Height = height; + d3d12->chain.back_buffer.desc.Format = + d3d12->shader_preset && d3d12->shader_preset->passes ? glslang_format_to_dxgi(d3d12->pass[d3d12->shader_preset->passes - 1].semantics.format) : DXGI_FORMAT_R8G8B8A8_UNORM; + d3d12->chain.back_buffer.desc.Flags = + D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; + d3d12->chain.back_buffer.srv_heap = + &d3d12->desc.srv_heap; + d3d12->chain.back_buffer.rt_view.ptr = + d3d12->desc.rtv_heap.cpu.ptr + + (countof(d3d12->chain.renderTargets)) + * d3d12->desc.rtv_heap.stride; + d3d12_init_texture(d3d12->device, &d3d12->chain.back_buffer); +#endif + + d3d12->chain.viewport.Width = width; + d3d12->chain.viewport.Height = height; + d3d12->chain.scissorRect.right = width; + d3d12->chain.scissorRect.bottom = height; + + return true; +} + +static void d3d12_init_base(d3d12_video_t* d3d12) +{ + int i = 0; + DXGIAdapter adapter = NULL; +#ifdef DEBUG +#ifdef __WINRT__ + if (SUCCEEDED(D3D12GetDebugInterface_(&d3d12->debugController))) + d3d12->debugController->lpVtbl->EnableDebugLayer(&d3d12->debugController); +#else + if (SUCCEEDED(D3D12GetDebugInterface_(&d3d12->debugController))) + d3d12->debugController->lpVtbl->EnableDebugLayer(d3d12->debugController); +#endif +#endif + +#ifdef __WINRT__ + DXGICreateFactory2(&d3d12->factory); +#else + DXGICreateFactory(&d3d12->factory); +#endif + { + settings_t *settings = config_get_ptr(); + int gpu_index = settings->ints.d3d12_gpu_index; + + if (d3d12->gpu_list) + string_list_free(d3d12->gpu_list); + + d3d12->gpu_list = string_list_new(); + + for (;;) + { + char str[128]; + union string_list_elem_attr attr = {0}; + DXGI_ADAPTER_DESC desc = {0}; + + str[0] = '\0'; + +#ifdef __WINRT__ + if (FAILED(DXGIEnumAdapters2(d3d12->factory, i, &adapter))) + break; +#else + if (FAILED(DXGIEnumAdapters(d3d12->factory, i, &adapter))) + break; +#endif +#ifdef __cplusplus + adapter->GetDesc(adapter, &desc); +#else + adapter->lpVtbl->GetDesc(adapter, &desc); +#endif + + utf16_to_char_string((const uint16_t*)desc.Description, str, sizeof(str)); + + RARCH_LOG("[D3D12]: Found GPU at index %d: \"%s\".\n", i, str); + + string_list_append(d3d12->gpu_list, str, attr); + + if (i < D3D12_MAX_GPU_COUNT) + { + AddRef(adapter); + d3d12->adapters[i] = adapter; + } + Release(adapter); + adapter = NULL; + + i++; + if (i >= D3D12_MAX_GPU_COUNT) + break; + } + + video_driver_set_gpu_api_devices(GFX_CTX_DIRECT3D12_API, d3d12->gpu_list); + + if (0 <= gpu_index && gpu_index <= i && gpu_index < D3D12_MAX_GPU_COUNT) + { + d3d12->adapter = d3d12->adapters[gpu_index]; + AddRef(d3d12->adapter); + RARCH_LOG("[D3D12]: Using GPU index %d.\n", gpu_index); + video_driver_set_gpu_device_string( + d3d12->gpu_list->elems[gpu_index].data); + } + else + { + RARCH_WARN("[D3D12]: Invalid GPU index %d, using first device found.\n", gpu_index); + d3d12->adapter = d3d12->adapters[0]; + AddRef(d3d12->adapter); + } + + if (!SUCCEEDED(D3D12CreateDevice_(d3d12->adapter, D3D_FEATURE_LEVEL_11_0, &d3d12->device))) + RARCH_WARN("[D3D12]: Could not create D3D12 device.\n"); + } +} + +static inline void d3d12_release_descriptor_heap(d3d12_descriptor_heap_t* heap) +{ + free(heap->map); + Release(heap->handle); +} + +static void d3d12_init_descriptor_heap(D3D12Device device, d3d12_descriptor_heap_t* out) +{ + D3D12CreateDescriptorHeap(device, &out->desc, &out->handle); + 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 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; +} + + +static void d3d12_init_descriptors(d3d12_video_t* d3d12) +{ + int i, j; + D3D12_ROOT_SIGNATURE_DESC desc; + D3D12_DESCRIPTOR_RANGE srv_tbl[1] = { { D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1 } }; + D3D12_DESCRIPTOR_RANGE uav_tbl[1] = { { D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1 } }; + D3D12_DESCRIPTOR_RANGE sampler_tbl[1] = { { D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, 1 } }; + D3D12_STATIC_SAMPLER_DESC static_sampler = { D3D12_FILTER_MIN_MAG_MIP_POINT }; + D3D12_ROOT_PARAMETER root_params[ROOT_ID_MAX]; + D3D12_ROOT_PARAMETER cs_root_params[CS_ROOT_ID_MAX]; + + root_params[ROOT_ID_TEXTURE_T].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + root_params[ROOT_ID_TEXTURE_T].DescriptorTable.NumDescriptorRanges = countof(srv_tbl); + root_params[ROOT_ID_TEXTURE_T].DescriptorTable.pDescriptorRanges = srv_tbl; + root_params[ROOT_ID_TEXTURE_T].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; + + root_params[ROOT_ID_SAMPLER_T].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + root_params[ROOT_ID_SAMPLER_T].DescriptorTable.NumDescriptorRanges = countof(sampler_tbl); + root_params[ROOT_ID_SAMPLER_T].DescriptorTable.pDescriptorRanges = sampler_tbl; + root_params[ROOT_ID_SAMPLER_T].ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; + + root_params[ROOT_ID_UBO].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; + root_params[ROOT_ID_UBO].Descriptor.RegisterSpace = 0; + root_params[ROOT_ID_UBO].Descriptor.ShaderRegister = 0; + root_params[ROOT_ID_UBO].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + + root_params[ROOT_ID_PC].ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV; + root_params[ROOT_ID_PC].Descriptor.RegisterSpace = 0; + root_params[ROOT_ID_PC].Descriptor.ShaderRegister = 1; + root_params[ROOT_ID_PC].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + + desc.NumParameters = countof(root_params); + desc.pParameters = root_params; + desc.NumStaticSamplers = 0; + desc.pStaticSamplers = NULL; + desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; + + d3d12_create_root_signature(d3d12->device, &desc, &d3d12->desc.rootSignature); + + 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); + + cs_root_params[CS_ROOT_ID_TEXTURE_T].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + cs_root_params[CS_ROOT_ID_TEXTURE_T].DescriptorTable.NumDescriptorRanges = countof(srv_tbl); + cs_root_params[CS_ROOT_ID_TEXTURE_T].DescriptorTable.pDescriptorRanges = srv_tbl; + cs_root_params[CS_ROOT_ID_TEXTURE_T].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + + cs_root_params[CS_ROOT_ID_UAV_T].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + cs_root_params[CS_ROOT_ID_UAV_T].DescriptorTable.NumDescriptorRanges = countof(uav_tbl); + cs_root_params[CS_ROOT_ID_UAV_T].DescriptorTable.pDescriptorRanges = uav_tbl; + cs_root_params[CS_ROOT_ID_UAV_T].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + + cs_root_params[CS_ROOT_ID_CONSTANTS].ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; + cs_root_params[CS_ROOT_ID_CONSTANTS].Constants.Num32BitValues = 3; + cs_root_params[CS_ROOT_ID_CONSTANTS].Constants.RegisterSpace = 0; + cs_root_params[CS_ROOT_ID_CONSTANTS].Constants.ShaderRegister = 0; + cs_root_params[CS_ROOT_ID_CONSTANTS].ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + + static_sampler.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + static_sampler.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + static_sampler.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; +#if 0 + static_sampler.MaxAnisotropy = 1; + static_sampler.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; + static_sampler.MinLOD = -D3D12_FLOAT32_MAX; + static_sampler.MaxLOD = D3D12_FLOAT32_MAX; +#endif + + desc.NumParameters = countof(cs_root_params); + desc.pParameters = cs_root_params; + desc.NumStaticSamplers = 1; + desc.pStaticSamplers = &static_sampler; + desc.Flags = D3D12_ROOT_SIGNATURE_FLAG_DENY_VERTEX_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS; + + d3d12_create_root_signature(d3d12->device, &desc, &d3d12->desc.cs_rootSignature); + + d3d12->desc.rtv_heap.desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + d3d12->desc.rtv_heap.desc.NumDescriptors = countof(d3d12->chain.renderTargets) + GFX_MAX_SHADERS * 2; + d3d12->desc.rtv_heap.desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + d3d12_init_descriptor_heap(d3d12->device, &d3d12->desc.rtv_heap); + + d3d12->desc.srv_heap.desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + d3d12->desc.srv_heap.desc.NumDescriptors = SLANG_NUM_BINDINGS * GFX_MAX_SHADERS + 2048; + d3d12->desc.srv_heap.desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + d3d12_init_descriptor_heap(d3d12->device, &d3d12->desc.srv_heap); + + d3d12->desc.sampler_heap.desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER; + d3d12->desc.sampler_heap.desc.NumDescriptors = + SLANG_NUM_BINDINGS * GFX_MAX_SHADERS + 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); + + for (i = 0; i < countof(d3d12->chain.renderTargets); i++) + { + d3d12->chain.desc_handles[i].ptr = + d3d12->desc.rtv_heap.cpu.ptr + i * d3d12->desc.rtv_heap.stride; + } + + for (i = 0; i < GFX_MAX_SHADERS; i++) + { + d3d12->pass[i].rt.rt_view.ptr = + d3d12->desc.rtv_heap.cpu.ptr + + (countof(d3d12->chain.renderTargets) + (2 * i)) * d3d12->desc.rtv_heap.stride; + d3d12->pass[i].feedback.rt_view.ptr = d3d12->pass[i].rt.rt_view.ptr + d3d12->desc.rtv_heap.stride; + + d3d12->pass[i].textures.ptr = d3d12_descriptor_heap_slot_alloc(&d3d12->desc.srv_heap).ptr - + d3d12->desc.srv_heap.cpu.ptr + d3d12->desc.srv_heap.gpu.ptr; + d3d12->pass[i].samplers.ptr = + d3d12_descriptor_heap_slot_alloc(&d3d12->desc.sampler_heap).ptr - + d3d12->desc.sampler_heap.cpu.ptr + d3d12->desc.sampler_heap.gpu.ptr; + + for (j = 1; j < SLANG_NUM_BINDINGS; j++) + { + d3d12_descriptor_heap_slot_alloc(&d3d12->desc.srv_heap); + d3d12_descriptor_heap_slot_alloc(&d3d12->desc.sampler_heap); + } + } +} + +static INLINE D3D12_GPU_DESCRIPTOR_HANDLE + d3d12_create_sampler(D3D12Device device, D3D12_SAMPLER_DESC* desc, d3d12_descriptor_heap_t* heap) +{ + 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 }; + + D3D12CreateSampler(device, desc, cpu_handle); + return gpu_handle; +} + +static 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++) + { + switch (i) + { + default: + case RARCH_WRAP_BORDER: + desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_BORDER; + break; + + 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); + } +} + +static void d3d12_init_queue(d3d12_video_t* d3d12) +{ + { + static const D3D12_COMMAND_QUEUE_DESC desc = { + D3D12_COMMAND_LIST_TYPE_DIRECT, + 0, + D3D12_COMMAND_QUEUE_FLAG_NONE, + 0 + }; + D3D12CreateCommandQueue( + d3d12->device, + (D3D12_COMMAND_QUEUE_DESC*)&desc, + &d3d12->queue.handle); + } + + D3D12CreateCommandAllocator( + d3d12->device, + D3D12_COMMAND_LIST_TYPE_DIRECT, + &d3d12->queue.allocator); + + D3D12CreateGraphicsCommandList( + d3d12->device, 0, D3D12_COMMAND_LIST_TYPE_DIRECT, d3d12->queue.allocator, + d3d12->pipes[VIDEO_SHADER_STOCK_BLEND], &d3d12->queue.cmd); + + D3D12CloseGraphicsCommandList(d3d12->queue.cmd); + + D3D12CreateFence(d3d12->device, 0, D3D12_FENCE_FLAG_NONE, &d3d12->queue.fence); + d3d12->queue.fenceValue = 0; + d3d12->queue.fenceEvent = CreateEvent(NULL, FALSE, FALSE, NULL); +} + +static void d3d12_create_fullscreen_quad_vbo( + D3D12Device device, D3D12_VERTEX_BUFFER_VIEW* view, D3D12Resource* vbo) +{ + void *vertex_data_begin = NULL; + D3D12_RANGE read_range = { 0, 0 }; + static const d3d12_vertex_t vertices[] = { + { { 0.0f, 0.0f }, { 0.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 0.0f, 1.0f }, { 0.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 1.0f, 0.0f }, { 1.0f, 1.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + { { 1.0f, 1.0f }, { 1.0f, 0.0f }, { 1.0f, 1.0f, 1.0f, 1.0f } }, + }; + + view->SizeInBytes = sizeof(vertices); + view->StrideInBytes = sizeof(*vertices); + view->BufferLocation = d3d12_create_buffer(device, view->SizeInBytes, vbo); + + D3D12Map(*vbo, 0, &read_range, &vertex_data_begin); + memcpy(vertex_data_begin, vertices, sizeof(vertices)); + D3D12Unmap(*vbo, 0, NULL); +} + static void *d3d12_gfx_init(const video_info_t* video, input_driver_t** input, void** input_data) { @@ -1187,17 +1752,13 @@ static void *d3d12_gfx_init(const video_info_t* video, d3d_input_driver(settings->arrays.input_driver, settings->arrays.input_joypad_driver, input, input_data); - if (!d3d12_init_base(d3d12)) - goto error; - - if (!d3d12_init_descriptors(d3d12)) - goto error; + d3d12_init_base(d3d12); + d3d12_init_descriptors(d3d12); if (!d3d12_gfx_init_pipelines(d3d12)) goto error; - if (!d3d12_init_queue(d3d12)) - goto error; + d3d12_init_queue(d3d12); #ifdef __WINRT__ if (!d3d12_init_swapchain(d3d12, d3d12->vp.full_width, d3d12->vp.full_height, uwp_get_corewindow()))