diff --git a/Makefile.common b/Makefile.common index b183da5e5f..db49fc94b3 100644 --- a/Makefile.common +++ b/Makefile.common @@ -1271,6 +1271,9 @@ ifeq ($(HAVE_D3D12), 1) 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 + HAVE_SLANG = 1 + HAVE_GLSLANG = 1 + HAVE_SPIRV_CROSS = 1 endif ifneq ($(findstring 1, $(HAVE_D3D10) $(HAVE_D3D11) $(HAVE_D3D12)),) diff --git a/configuration.c b/configuration.c index f6e65748f1..6601328ae5 100644 --- a/configuration.c +++ b/configuration.c @@ -2272,6 +2272,7 @@ static bool check_shader_compatibility(enum file_path_enum enum_idx) if (string_is_equal(settings->arrays.video_driver, "vulkan") || string_is_equal(settings->arrays.video_driver, "d3d11") || + string_is_equal(settings->arrays.video_driver, "d3d12") || string_is_equal(settings->arrays.video_driver, "gx2")) { if (enum_idx != FILE_PATH_SLANGP_EXTENSION) diff --git a/gfx/common/d3d11_common.h b/gfx/common/d3d11_common.h index 0e7f72538c..388e1a3f47 100644 --- a/gfx/common/d3d11_common.h +++ b/gfx/common/d3d11_common.h @@ -2423,14 +2423,6 @@ D3D11UnmapBuffer(D3D11DeviceContext device_context, D3D11Buffer buffer, UINT sub #include "../video_driver.h" #include "../drivers_shader/slang_process.h" -typedef struct -{ - float x; - float y; - float z; - float w; -} float4_t; - typedef struct d3d11_vertex_t { float position[2]; diff --git a/gfx/common/d3d12_common.c b/gfx/common/d3d12_common.c index 9a39dcc24d..cecbc0d1be 100644 --- a/gfx/common/d3d12_common.c +++ b/gfx/common/d3d12_common.c @@ -235,8 +235,6 @@ 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->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]); @@ -328,10 +326,11 @@ bool d3d12_create_root_signature( bool d3d12_init_descriptors(d3d12_video_t* d3d12) { + int i, j; D3D12_ROOT_SIGNATURE_DESC desc; - D3D12_DESCRIPTOR_RANGE srv_tbl[] = { { D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1 } }; - D3D12_DESCRIPTOR_RANGE uav_tbl[] = { { D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1 } }; - D3D12_DESCRIPTOR_RANGE sampler_tbl[] = { { D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, 1 } }; + 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]; @@ -351,6 +350,11 @@ bool d3d12_init_descriptors(d3d12_video_t* d3d12) 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; @@ -407,15 +411,41 @@ bool d3d12_init_descriptors(d3d12_video_t* d3d12) 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 = 1024; + d3d12->desc.srv_heap.desc.NumDescriptors = SLANG_NUM_BINDINGS * GFX_MAX_SHADERS + 1024; 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 = 2 * RARCH_WRAP_MAX; - d3d12->desc.sampler_heap.desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + 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) + i) * 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; } @@ -577,9 +607,14 @@ void d3d12_release_texture(d3d12_texture_t* texture) } void d3d12_init_texture(D3D12Device device, d3d12_texture_t* texture) { + int i; d3d12_release_texture(texture); - if (texture->desc.MipLevels > 1) + if (!texture->desc.MipLevels) + texture->desc.MipLevels = 1; + + if (!(texture->desc.Width >> (texture->desc.MipLevels - 1)) && + !(texture->desc.Height >> (texture->desc.MipLevels - 1))) { unsigned width = texture->desc.Width >> 5; unsigned height = texture->desc.Height >> 5; @@ -591,8 +626,6 @@ void d3d12_init_texture(D3D12Device device, d3d12_texture_t* texture) texture->desc.MipLevels++; } } - else - texture->desc.MipLevels = 1; { D3D12_FEATURE_DATA_FORMAT_SUPPORT format_support = { @@ -621,38 +654,39 @@ void d3d12_init_texture(D3D12Device device, d3d12_texture_t* texture) D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, NULL, &texture->handle); } - if (texture->srv_heap) - { - int i; - D3D12_SHADER_RESOURCE_VIEW_DESC view_desc = { texture->desc.Format }; + assert(texture->srv_heap); - view_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; - view_desc.Texture2D.MipLevels = texture->desc.MipLevels; + { + D3D12_SHADER_RESOURCE_VIEW_DESC desc = { texture->desc.Format }; + + desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + desc.Texture2D.MipLevels = texture->desc.MipLevels; texture->cpu_descriptor[0] = d3d12_descriptor_heap_slot_alloc(texture->srv_heap); - D3D12CreateShaderResourceView( - device, texture->handle, &view_desc, texture->cpu_descriptor[0]); + D3D12CreateShaderResourceView(device, texture->handle, &desc, texture->cpu_descriptor[0]); texture->gpu_descriptor[0].ptr = texture->cpu_descriptor[0].ptr - texture->srv_heap->cpu.ptr + texture->srv_heap->gpu.ptr; + } - for (i = 1; i < texture->desc.MipLevels; i++) - { - D3D12_UNORDERED_ACCESS_VIEW_DESC desc = { texture->desc.Format }; + for (i = 1; i < texture->desc.MipLevels; i++) + { + D3D12_UNORDERED_ACCESS_VIEW_DESC desc = { texture->desc.Format }; - desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; - desc.Texture2D.MipSlice = i; + desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; + desc.Texture2D.MipSlice = i; - texture->cpu_descriptor[i] = d3d12_descriptor_heap_slot_alloc(texture->srv_heap); - D3D12CreateUnorderedAccessView( - device, texture->handle, NULL, &desc, texture->cpu_descriptor[i]); - texture->gpu_descriptor[i].ptr = texture->cpu_descriptor[i].ptr - - texture->srv_heap->cpu.ptr + texture->srv_heap->gpu.ptr; - } + texture->cpu_descriptor[i] = d3d12_descriptor_heap_slot_alloc(texture->srv_heap); + D3D12CreateUnorderedAccessView( + device, texture->handle, NULL, &desc, texture->cpu_descriptor[i]); + texture->gpu_descriptor[i].ptr = texture->cpu_descriptor[i].ptr - texture->srv_heap->cpu.ptr + + texture->srv_heap->gpu.ptr; } if (texture->desc.Flags & D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET) { + assert(texture->rt_view.ptr); + D3D12CreateRenderTargetView(device, texture->handle, NULL, texture->rt_view); } else { @@ -670,11 +704,19 @@ void d3d12_init_texture(D3D12Device device, d3d12_texture_t* texture) buffer_desc.MipLevels = 1; buffer_desc.SampleDesc.Count = 1; buffer_desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; +#if 0 + buffer_desc.Flags = D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE; +#endif D3D12CreateCommittedResource( device, &heap_props, D3D12_HEAP_FLAG_NONE, &buffer_desc, D3D12_RESOURCE_STATE_GENERIC_READ, NULL, &texture->upload_buffer); } + + texture->size_data.x = texture->desc.Width; + texture->size_data.y = texture->desc.Height; + texture->size_data.z = 1.0f / texture->desc.Width; + texture->size_data.w = 1.0f / texture->desc.Height; } void d3d12_update_texture( diff --git a/gfx/common/d3d12_common.h b/gfx/common/d3d12_common.h index bb8a0d613c..fb2b653326 100644 --- a/gfx/common/d3d12_common.h +++ b/gfx/common/d3d12_common.h @@ -1306,12 +1306,14 @@ typedef struct D3D12_CPU_DESCRIPTOR_HANDLE cpu_descriptor[D3D12_MAX_TEXTURE_DIMENSION_2_TO_EXP - 5]; D3D12_GPU_DESCRIPTOR_HANDLE gpu_descriptor[D3D12_MAX_TEXTURE_DIMENSION_2_TO_EXP - 5]; D3D12_GPU_DESCRIPTOR_HANDLE sampler; + D3D12_CPU_DESCRIPTOR_HANDLE rt_view; D3D12_PLACED_SUBRESOURCE_FOOTPRINT layout; UINT num_rows; UINT64 row_size_in_bytes; UINT64 total_bytes; d3d12_descriptor_heap_t* srv_heap; bool dirty; + float4_t size_data; } d3d12_texture_t; #ifndef ALIGN @@ -1377,13 +1379,14 @@ typedef struct struct { + d3d12_texture_t texture[GFX_MAX_FRAME_HISTORY + 1]; D3D12Resource ubo; D3D12_CONSTANT_BUFFER_VIEW_DESC ubo_view; D3D12Resource vbo; D3D12_VERTEX_BUFFER_VIEW vbo_view; - d3d12_texture_t texture; D3D12_VIEWPORT viewport; D3D12_RECT scissorRect; + float4_t output_size; int rotation; } frame; @@ -1411,6 +1414,25 @@ typedef struct bool enabled; } sprites; + struct + { + D3D12PipelineState pipe; + D3D12_GPU_DESCRIPTOR_HANDLE sampler; + D3D12Resource buffers[SLANG_CBUFFER_MAX]; + D3D12_CONSTANT_BUFFER_VIEW_DESC buffer_view[SLANG_CBUFFER_MAX]; + d3d12_texture_t rt; + d3d12_texture_t feedback; + D3D12_VIEWPORT viewport; + D3D12_RECT scissorRect; + pass_semantics_t semantics; + uint32_t frame_count; + D3D12_GPU_DESCRIPTOR_HANDLE textures; + D3D12_GPU_DESCRIPTOR_HANDLE samplers; + } pass[GFX_MAX_SHADERS]; + + struct video_shader* shader_preset; + d3d12_texture_t luts[GFX_MAX_TEXTURES]; + D3D12PipelineState pipes[GFX_MAX_SHADERS]; D3D12PipelineState mipmapgen_pipe; d3d12_uniform_t ubo_values; @@ -1423,6 +1445,8 @@ typedef struct bool resize_chain; bool keep_aspect; bool resize_viewport; + bool resize_render_targets; + bool init_history; D3D12Resource menu_pipeline_vbo; D3D12_VERTEX_BUFFER_VIEW menu_pipeline_vbo_view; @@ -1435,6 +1459,7 @@ typedef enum { ROOT_ID_TEXTURE_T = 0, ROOT_ID_SAMPLER_T, ROOT_ID_UBO, + ROOT_ID_PC, ROOT_ID_MAX, } root_signature_parameter_index_t; diff --git a/gfx/common/d3dcompiler_common.c b/gfx/common/d3dcompiler_common.c index 42e28886ee..6da87c1ba4 100644 --- a/gfx/common/d3dcompiler_common.c +++ b/gfx/common/d3dcompiler_common.c @@ -16,6 +16,7 @@ #define CINTERFACE #include +#include #ifdef HAVE_CONFIG_H #include "config.h" @@ -131,6 +132,10 @@ bool d3d_compile(const char* src, size_t size, LPCSTR src_name, LPCSTR entrypoin compileflags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION; #endif + + if (!size) + size = strlen(src); + if (FAILED(D3DCompile( src, size, src_name, NULL, NULL, entrypoint, target, compileflags, 0, out, &error_msg))) { diff --git a/gfx/common/dxgi_common.h b/gfx/common/dxgi_common.h index aefdafaa2e..a35090dfb5 100644 --- a/gfx/common/dxgi_common.h +++ b/gfx/common/dxgi_common.h @@ -770,6 +770,14 @@ typedef enum { DXGI_FORMAT_EX_A4R4G4B4_UNORM = 1000, } DXGI_FORMAT_EX; +typedef struct +{ + float x; + float y; + float z; + float w; +} float4_t; + RETRO_BEGIN_DECLS DXGI_FORMAT* dxgi_get_format_fallback_list(DXGI_FORMAT format); diff --git a/gfx/drivers/d3d12.c b/gfx/drivers/d3d12.c index c1f0aadd37..6b5908c28d 100644 --- a/gfx/drivers/d3d12.c +++ b/gfx/drivers/d3d12.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "../video_driver.h" #include "../font_driver.h" @@ -86,19 +87,292 @@ static void d3d12_update_viewport(void* data, bool force_full) d3d12->frame.scissorRect.right = d3d12->vp.x + d3d12->vp.width; d3d12->frame.scissorRect.bottom = d3d12->vp.y + d3d12->vp.height; + if (d3d12->shader_preset && (d3d12->frame.output_size.x != d3d12->vp.width || + d3d12->frame.output_size.y != d3d12->vp.height)) + d3d12->resize_render_targets = true; + + d3d12->frame.output_size.x = d3d12->vp.width; + d3d12->frame.output_size.y = d3d12->vp.height; + d3d12->frame.output_size.z = 1.0f / d3d12->vp.width; + d3d12->frame.output_size.w = 1.0f / d3d12->vp.height; + d3d12->resize_viewport = false; } +static void d3d12_free_shader_preset(d3d12_video_t* d3d12) +{ + unsigned i; + if (!d3d12->shader_preset) + return; + + for (i = 0; i < d3d12->shader_preset->passes; i++) + { + unsigned j; + + free(d3d12->shader_preset->pass[i].source.string.vertex); + free(d3d12->shader_preset->pass[i].source.string.fragment); + free(d3d12->pass[i].semantics.textures); + d3d12_release_texture(&d3d12->pass[i].rt); + d3d12_release_texture(&d3d12->pass[i].feedback); + + for (j = 0; j < SLANG_CBUFFER_MAX; j++) + { + free(d3d12->pass[i].semantics.cbuffers[j].uniforms); + Release(d3d12->pass[i].buffers[j]); + } + + Release(d3d12->pass[i].pipe); + } + + memset(d3d12->pass, 0, sizeof(d3d12->pass)); + + /* only free the history textures here */ + for (i = 1; i <= d3d12->shader_preset->history_size; i++) + d3d12_release_texture(&d3d12->frame.texture[i]); + + memset( + &d3d12->frame.texture[1], 0, + sizeof(d3d12->frame.texture[1]) * d3d12->shader_preset->history_size); + + for (i = 0; i < d3d12->shader_preset->luts; i++) + d3d12_release_texture(&d3d12->luts[i]); + + memset(d3d12->luts, 0, sizeof(d3d12->luts)); + + free(d3d12->shader_preset); + d3d12->shader_preset = NULL; + d3d12->init_history = false; + d3d12->resize_render_targets = false; +} + +static bool d3d12_gfx_set_shader(void* data, enum rarch_shader_type type, const char* path) +{ +#if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS) + unsigned i; + d3d12_texture_t* source; + d3d12_video_t* d3d12 = (d3d12_video_t*)data; + + if (!d3d12) + return false; + + d3d12_free_shader_preset(d3d12); + + if (!path) + return true; + + if (type != RARCH_SHADER_SLANG) + { + RARCH_WARN("Only .slang or .slangp shaders are supported. Falling back to stock.\n"); + return false; + } + + config_file_t* conf = config_file_new(path); + + if (!conf) + return false; + + d3d12->shader_preset = (struct video_shader*)calloc(1, sizeof(*d3d12->shader_preset)); + + if (!video_shader_read_conf_cgp(conf, d3d12->shader_preset)) + goto error; + + video_shader_resolve_relative(d3d12->shader_preset, path); + + source = &d3d12->frame.texture[0]; + for (i = 0; i < d3d12->shader_preset->passes; source = &d3d12->pass[i++].rt) + { + unsigned j; + /* clang-format off */ + semantics_map_t semantics_map = { + { + /* Original */ + { &d3d12->frame.texture[0], 0, + &d3d12->frame.texture[0].size_data, 0, + &d3d12->pass[i].sampler, 0 }, + + /* Source */ + { source, 0, + &source->size_data, 0, + &d3d12->pass[i].sampler, 0 }, + + /* OriginalHistory */ + { &d3d12->frame.texture[0], sizeof(*d3d12->frame.texture), + &d3d12->frame.texture[0].size_data, sizeof(*d3d12->frame.texture), + &d3d12->pass[i].sampler, 0 }, + + /* PassOutput */ + { &d3d12->pass[0].rt, sizeof(*d3d12->pass), + &d3d12->pass[0].rt.size_data, sizeof(*d3d12->pass), + &d3d12->pass[i].sampler, 0 }, + + /* PassFeedback */ + { &d3d12->pass[0].feedback, sizeof(*d3d12->pass), + &d3d12->pass[0].feedback.size_data, sizeof(*d3d12->pass), + &d3d12->pass[i].sampler, 0 }, + + /* User */ + { &d3d12->luts[0], sizeof(*d3d12->luts), + &d3d12->luts[0].size_data, sizeof(*d3d12->luts), + &d3d12->luts[0].sampler, sizeof(*d3d12->luts) }, + }, + { + &d3d12->mvp, /* MVP */ + &d3d12->pass[i].rt.size_data, /* OutputSize */ + &d3d12->frame.output_size, /* FinalViewportSize */ + &d3d12->pass[i].frame_count, /* FrameCount */ + } + }; + /* clang-format on */ + + if (!slang_process( + d3d12->shader_preset, i, RARCH_SHADER_HLSL, 50, &semantics_map, + &d3d12->pass[i].semantics)) + goto error; + + { + D3DBlob vs_code = NULL; + D3DBlob ps_code = NULL; + D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = { d3d12->desc.sl_rootSignature }; + + static const D3D12_INPUT_ELEMENT_DESC inputElementDesc[] = { + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d12_vertex_t, position), + D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 1, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(d3d12_vertex_t, texcoord), + D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + }; +#ifdef DEBUG + bool save_hlsl = true; +#else + bool save_hlsl = false; +#endif + static const char vs_ext[] = ".vs.hlsl"; + static const char ps_ext[] = ".ps.hlsl"; + char vs_path[PATH_MAX_LENGTH]; + char ps_path[PATH_MAX_LENGTH]; + const char* slang_path = d3d12->shader_preset->pass[i].source.path; + const char* vs_src = d3d12->shader_preset->pass[i].source.string.vertex; + const char* ps_src = d3d12->shader_preset->pass[i].source.string.fragment; + int base_len = strlen(slang_path) - strlen(".slang"); + + if (base_len <= 0) + base_len = strlen(slang_path); + + strncpy(vs_path, slang_path, base_len); + strncpy(ps_path, slang_path, base_len); + strncpy(vs_path + base_len, vs_ext, sizeof(vs_ext)); + strncpy(ps_path + base_len, ps_ext, sizeof(ps_ext)); + + if (!d3d_compile(vs_src, 0, vs_path, "main", "vs_5_0", &vs_code)) + save_hlsl = true; + if (!d3d_compile(ps_src, 0, ps_path, "main", "ps_5_0", &ps_code)) + save_hlsl = true; + + desc.BlendState.RenderTarget[0] = d3d12_blend_enable_desc; + desc.RTVFormats[0] = glslang_format_to_dxgi(d3d12->pass[i].semantics.format); + 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->pass[i].pipe)) + save_hlsl = true; + + if (save_hlsl) + { + FILE* fp = fopen(vs_path, "w"); + fwrite(vs_src, 1, strlen(vs_src), fp); + fclose(fp); + + fp = fopen(ps_path, "w"); + fwrite(ps_src, 1, strlen(ps_src), fp); + fclose(fp); + } + + free(d3d12->shader_preset->pass[i].source.string.vertex); + free(d3d12->shader_preset->pass[i].source.string.fragment); + + d3d12->shader_preset->pass[i].source.string.vertex = NULL; + d3d12->shader_preset->pass[i].source.string.fragment = NULL; + + Release(vs_code); + Release(ps_code); + + if (!d3d12->pass[i].pipe) + goto error; + + d3d12->pass[i].rt.rt_view.ptr = + d3d12->desc.rtv_heap.cpu.ptr + + (countof(d3d12->chain.renderTargets) + i) * d3d12->desc.rtv_heap.stride; + + d3d12->pass[i].textures.ptr = + d3d12->desc.srv_heap.gpu.ptr + i * SLANG_NUM_SEMANTICS * d3d12->desc.srv_heap.stride; + d3d12->pass[i].samplers.ptr = d3d12->desc.sampler_heap.gpu.ptr + + i * SLANG_NUM_SEMANTICS * d3d12->desc.sampler_heap.stride; + } + + for (j = 0; j < SLANG_CBUFFER_MAX; j++) + { + if (!d3d12->pass[i].semantics.cbuffers[j].size) + continue; + + d3d12->pass[i].buffer_view[j].SizeInBytes = d3d12->pass[i].semantics.cbuffers[j].size; + d3d12->pass[i].buffer_view[j].BufferLocation = d3d12_create_buffer( + d3d12->device, d3d12->pass[i].buffer_view[j].SizeInBytes, + &d3d12->pass[i].buffers[j]); + } + } + + for (i = 0; i < d3d12->shader_preset->luts; i++) + { + struct texture_image image = { 0 }; + image.supports_rgba = true; + + if (!image_texture_load(&image, d3d12->shader_preset->lut[i].path)) + goto error; + + d3d12->luts[i].desc.Width = image.width; + d3d12->luts[i].desc.Height = image.height; + d3d12->luts[i].desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + d3d12->luts[i].srv_heap = &d3d12->desc.srv_heap; + + if (d3d12->shader_preset->lut[i].mipmap) + d3d12->luts[i].desc.MipLevels = UINT16_MAX; + + d3d12_init_texture(d3d12->device, &d3d12->luts[i]); + + d3d12_update_texture( + image.width, image.height, 0, DXGI_FORMAT_R8G8B8A8_UNORM, image.pixels, + &d3d12->luts[i]); + + image_texture_free(&image); + + d3d12->luts[i].sampler = + d3d12->samplers[d3d12->shader_preset->lut[i].filter][d3d12->shader_preset->lut[i].wrap]; + } + + video_shader_resolve_current_parameters(conf, d3d12->shader_preset); + config_file_free(conf); + + d3d12->resize_render_targets = true; + d3d12->init_history = true; + + return true; + +error: + d3d12_free_shader_preset(d3d12); +#endif + return false; +} + static bool d3d12_gfx_init_pipelines(d3d12_video_t* d3d12) { D3DBlob vs_code = NULL; D3DBlob ps_code = NULL; D3DBlob gs_code = NULL; D3DBlob cs_code = NULL; - D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = { 0 }; + D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = { d3d12->desc.rootSignature }; desc.BlendState.RenderTarget[0] = d3d12_blend_enable_desc; - desc.pRootSignature = d3d12->desc.rootSignature; desc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; { @@ -329,15 +603,15 @@ static bool d3d12_gfx_init_pipelines(d3d12_video_t* d3d12) static const char shader[] = #include "d3d_shaders/mimpapgen_sm5.h" ; - D3D12_COMPUTE_PIPELINE_STATE_DESC desc = {d3d12->desc.cs_rootSignature}; + D3D12_COMPUTE_PIPELINE_STATE_DESC desc = { d3d12->desc.cs_rootSignature }; if (!d3d_compile(shader, sizeof(shader), NULL, "CSMain", "cs_5_0", &cs_code)) goto error; desc.CS.pShaderBytecode = D3DGetBufferPointer(cs_code); desc.CS.BytecodeLength = D3DGetBufferSize(cs_code); - if(!D3D12CreateComputePipelineState(d3d12->device, &desc, &d3d12->mipmapgen_pipe)) + if (!D3D12CreateComputePipelineState(d3d12->device, &desc, &d3d12->mipmapgen_pipe)) - Release(cs_code); + Release(cs_code); cs_code = NULL; } @@ -356,6 +630,11 @@ static void d3d12_gfx_free(void* data) unsigned i; d3d12_video_t* d3d12 = (d3d12_video_t*)data; + if (!d3d12) + return; + + d3d12_free_shader_preset(d3d12); + font_driver_free_osd(); Release(d3d12->sprites.vbo); @@ -363,8 +642,8 @@ static void d3d12_gfx_free(void* data) Release(d3d12->frame.ubo); Release(d3d12->frame.vbo); - Release(d3d12->frame.texture.handle); - Release(d3d12->frame.texture.upload_buffer); + Release(d3d12->frame.texture[0].handle); + Release(d3d12->frame.texture[0].upload_buffer); Release(d3d12->menu.vbo); Release(d3d12->menu.texture.handle); Release(d3d12->menu.texture.upload_buffer); @@ -501,10 +780,18 @@ d3d12_gfx_init(const video_info_t* video, const input_driver_t** input, void** i d3d12->keep_aspect = video->force_aspect; d3d12->chain.vsync = video->vsync; d3d12->format = video->rgb32 ? DXGI_FORMAT_B8G8R8X8_UNORM : DXGI_FORMAT_B5G6R5_UNORM; - d3d12->frame.texture.desc.Format = d3d12->format; + d3d12->frame.texture[0].desc.Format = d3d12->format; font_driver_init_osd(d3d12, false, video->is_threaded, FONT_DRIVER_RENDER_D3D12_API); + if (settings->bools.video_shader_enable) + { + const char* ext = path_get_extension(settings->paths.path_shader); + + if (ext && !strcmp(ext, "slangp")) + d3d12_gfx_set_shader(d3d12, RARCH_SHADER_SLANG, settings->paths.path_shader); + } + return d3d12; error: @@ -513,6 +800,133 @@ error: return NULL; } +static void d3d12_init_history(d3d12_video_t* d3d12, unsigned width, unsigned height) +{ + unsigned i; + + /* todo: should we init history to max_width/max_height instead ? + * to prevent out of memory errors happening several frames later + * and to reduce memory fragmentation */ + + assert(d3d12->shader_preset); + for (i = 0; i < d3d12->shader_preset->history_size + 1; i++) + { + d3d12->frame.texture[i].desc.Width = width; + d3d12->frame.texture[i].desc.Height = height; + d3d12->frame.texture[i].desc.Format = d3d12->frame.texture[0].desc.Format; + d3d12->frame.texture[i].desc.MipLevels = d3d12->frame.texture[0].desc.MipLevels; + d3d12->frame.texture[i].srv_heap = &d3d12->desc.srv_heap; + d3d12_init_texture(d3d12->device, &d3d12->frame.texture[i]); + /* todo: clear texture ? */ + } + d3d12->init_history = false; +} +static void d3d12_init_render_targets(d3d12_video_t* d3d12, unsigned width, unsigned height) +{ + unsigned i; + + assert(d3d12->shader_preset); + + for (i = 0; i < d3d12->shader_preset->passes; i++) + { + struct video_shader_pass* pass = &d3d12->shader_preset->pass[i]; + + if (pass->fbo.valid) + { + + switch (pass->fbo.type_x) + { + case RARCH_SCALE_INPUT: + width *= pass->fbo.scale_x; + break; + + case RARCH_SCALE_VIEWPORT: + width = d3d12->vp.width * pass->fbo.scale_x; + break; + + case RARCH_SCALE_ABSOLUTE: + width = pass->fbo.abs_x; + break; + + default: + break; + } + + if (!width) + width = d3d12->vp.width; + + switch (pass->fbo.type_y) + { + case RARCH_SCALE_INPUT: + height *= pass->fbo.scale_y; + break; + + case RARCH_SCALE_VIEWPORT: + height = d3d12->vp.height * pass->fbo.scale_y; + break; + + case RARCH_SCALE_ABSOLUTE: + height = pass->fbo.abs_y; + break; + + default: + break; + } + + if (!height) + height = d3d12->vp.height; + } + else if (i == (d3d12->shader_preset->passes - 1)) + { + width = d3d12->vp.width; + height = d3d12->vp.height; + } + + RARCH_LOG("[d3d12]: Updating framebuffer size %u x %u.\n", width, height); + + if ((i != (d3d12->shader_preset->passes - 1)) || (width != d3d12->vp.width) || + (height != d3d12->vp.height)) + { + d3d12->pass[i].viewport.Width = width; + d3d12->pass[i].viewport.Height = height; + d3d12->pass[i].viewport.MaxDepth = 1.0; + d3d12->pass[i].scissorRect.right = width; + d3d12->pass[i].scissorRect.bottom = height; + d3d12->pass[i].rt.desc.Width = width; + d3d12->pass[i].rt.desc.Height = height; + d3d12->pass[i].rt.desc.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; + d3d12->pass[i].rt.srv_heap = &d3d12->desc.srv_heap; + d3d12->pass[i].rt.desc.Format = glslang_format_to_dxgi(d3d12->pass[i].semantics.format); + d3d12_init_texture(d3d12->device, &d3d12->pass[i].rt); + + if (pass->feedback) + { + d3d12->pass[i].feedback.desc = d3d12->pass[i].rt.desc; + d3d12->pass[i].feedback.srv_heap = &d3d12->desc.srv_heap; + d3d12_init_texture(d3d12->device, &d3d12->pass[i].feedback); + /* todo: do we need to clear it to black here ? */ + } + } + else + { + d3d12->pass[i].rt.size_data.x = width; + d3d12->pass[i].rt.size_data.y = height; + d3d12->pass[i].rt.size_data.z = 1.0f / width; + d3d12->pass[i].rt.size_data.w = 1.0f / height; + } + + d3d12->pass[i].sampler = d3d12->samplers[pass->filter][pass->wrap]; + } + + d3d12->resize_render_targets = false; + +#if 0 +error: + d3d12_free_shader_preset(d3d12); + return false; +#endif +} + static bool d3d12_gfx_frame( void* data, const void* frame, @@ -523,7 +937,9 @@ static bool d3d12_gfx_frame( const char* msg, video_frame_info_t* video_info) { - d3d12_video_t* d3d12 = (d3d12_video_t*)data; + unsigned i; + d3d12_texture_t* texture = NULL; + d3d12_video_t* d3d12 = (d3d12_video_t*)data; if (d3d12->resize_chain) { @@ -561,13 +977,214 @@ static bool d3d12_gfx_frame( D3D12ResetGraphicsCommandList( d3d12->queue.cmd, d3d12->queue.allocator, d3d12->pipes[VIDEO_SHADER_STOCK_BLEND]); - D3D12SetGraphicsRootSignature(d3d12->queue.cmd, d3d12->desc.rootSignature); + { D3D12DescriptorHeap desc_heaps[] = { d3d12->desc.srv_heap.handle, d3d12->desc.sampler_heap.handle }; D3D12SetDescriptorHeaps(d3d12->queue.cmd, countof(desc_heaps), desc_heaps); } +#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); + + D3D12IASetPrimitiveTopology(d3d12->queue.cmd, D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + + if (data && width && height) + { + if (d3d12->shader_preset) + { + if (d3d12->frame.texture[0].desc.Width != width || + d3d12->frame.texture[0].desc.Height != height) + d3d12->resize_render_targets = true; + + if (d3d12->resize_render_targets) + { + /* release all render targets first to avoid memory fragmentation */ + for (i = 0; i < d3d12->shader_preset->passes; i++) + d3d12_release_texture(&d3d12->pass[i].rt); + } + + if (d3d12->shader_preset->history_size) + { + if (d3d12->init_history) + d3d12_init_history(d3d12, width, height); + else + { + int k; + /* todo: what about frame-duping ? + * maybe clone d3d12_texture_t with AddRef */ + d3d12_texture_t tmp = d3d12->frame.texture[d3d12->shader_preset->history_size]; + for (k = d3d12->shader_preset->history_size; k > 0; k--) + d3d12->frame.texture[k] = d3d12->frame.texture[k - 1]; + d3d12->frame.texture[0] = tmp; + } + } + } + + /* either no history, or we moved a texture of a different size in the front slot */ + if (d3d12->frame.texture[0].desc.Width != width || + d3d12->frame.texture[0].desc.Height != height) + { + d3d12->frame.texture[0].desc.Width = width; + d3d12->frame.texture[0].desc.Height = height; + d3d12->frame.texture[0].srv_heap = &d3d12->desc.srv_heap; + d3d12_init_texture(d3d12->device, &d3d12->frame.texture[0]); + } + + if (d3d12->resize_render_targets) + d3d12_init_render_targets(d3d12, width, height); + + d3d12_update_texture(width, height, pitch, d3d12->format, frame, &d3d12->frame.texture[0]); + + d3d12_upload_texture(d3d12->queue.cmd, &d3d12->frame.texture[0]); + } + D3D12IASetVertexBuffers(d3d12->queue.cmd, 0, 1, &d3d12->frame.vbo_view); + + texture = d3d12->frame.texture; + + if (d3d12->shader_preset) + { + D3D12SetGraphicsRootSignature(d3d12->queue.cmd, d3d12->desc.sl_rootSignature); + + for (i = 0; i < d3d12->shader_preset->passes; i++) + { + if (d3d12->shader_preset->pass[i].feedback) + { + d3d12_texture_t tmp = d3d12->pass[i].feedback; + d3d12->pass[i].feedback = d3d12->pass[i].rt; + d3d12->pass[i].rt = tmp; + } + } + + for (i = 0; i < d3d12->shader_preset->passes; i++) + { + unsigned j; + + D3D12SetPipelineState(d3d12->queue.cmd, d3d12->pass[i].pipe); + + if (d3d12->shader_preset->pass[i].frame_count_mod) + d3d12->pass[i].frame_count = + frame_count % d3d12->shader_preset->pass[i].frame_count_mod; + else + d3d12->pass[i].frame_count = frame_count; + + for (j = 0; j < SLANG_CBUFFER_MAX; j++) + { + cbuffer_sem_t* buffer_sem = &d3d12->pass[i].semantics.cbuffers[j]; + + if (buffer_sem->stage_mask && buffer_sem->uniforms) + { + D3D12_RANGE range = { 0, 0 }; + uint8_t* mapped_data = NULL; + uniform_sem_t* uniform = buffer_sem->uniforms; + + D3D12Map(d3d12->pass[i].buffers[j], 0, &range, (void**)&mapped_data); + while (uniform->size) + { + if (uniform->data) + memcpy(mapped_data + uniform->offset, uniform->data, uniform->size); + uniform++; + } + D3D12Unmap(d3d12->pass[i].buffers[j], 0, NULL); + + D3D12SetGraphicsRootConstantBufferView( + d3d12->queue.cmd, j == SLANG_CBUFFER_UBO ? ROOT_ID_UBO : ROOT_ID_PC, + d3d12->pass[i].buffer_view[j].BufferLocation); + } + } +#if 0 + D3D12OMSetRenderTargets(d3d12->queue.cmd, 1, NULL, FALSE, NULL); +#endif + + { + texture_sem_t* texture_sem = d3d12->pass[i].semantics.textures; + while (texture_sem->stage_mask) + { + { + D3D12_CPU_DESCRIPTOR_HANDLE handle = { + d3d12->pass[i].textures.ptr - d3d12->desc.srv_heap.gpu.ptr + + d3d12->desc.srv_heap.cpu.ptr + + texture_sem->binding * d3d12->desc.srv_heap.stride + }; + d3d12_texture_t* tex = texture_sem->texture_data; + D3D12_SHADER_RESOURCE_VIEW_DESC desc = { tex->desc.Format }; + + desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + desc.Texture2D.MipLevels = tex->desc.MipLevels; + + D3D12CreateShaderResourceView(d3d12->device, tex->handle, &desc, handle); + } + + { + D3D12_CPU_DESCRIPTOR_HANDLE handle = { + d3d12->pass[i].samplers.ptr - d3d12->desc.sampler_heap.gpu.ptr + + d3d12->desc.sampler_heap.cpu.ptr + + texture_sem->binding * d3d12->desc.sampler_heap.stride + }; + 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; + desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_BORDER; + desc.AddressV = desc.AddressU; + desc.AddressW = desc.AddressU; + desc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; + + D3D12CreateSampler(d3d12->device, &desc, handle); + } + + texture_sem++; + } + + D3D12SetGraphicsRootDescriptorTable( + d3d12->queue.cmd, ROOT_ID_TEXTURE_T, d3d12->pass[i].textures); + D3D12SetGraphicsRootDescriptorTable( + d3d12->queue.cmd, ROOT_ID_SAMPLER_T, d3d12->pass[i].samplers); + } + + if (d3d12->pass[i].rt.handle) + { + d3d12_resource_transition( + d3d12->queue.cmd, d3d12->pass[i].rt.handle, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET); + + D3D12OMSetRenderTargets(d3d12->queue.cmd, 1, &d3d12->pass[i].rt.rt_view, FALSE, NULL); +#if 0 + D3D12ClearRenderTargetView( + d3d12->queue.cmd, d3d12->pass[i].rt.rt_view, d3d12->chain.clearcolor, 0, NULL); +#endif + D3D12RSSetViewports(d3d12->queue.cmd, 1, &d3d12->pass[i].viewport); + D3D12RSSetScissorRects(d3d12->queue.cmd, 1, &d3d12->pass[i].scissorRect); + + D3D12DrawInstanced(d3d12->queue.cmd, 4, 1, 0, 0); + + d3d12_resource_transition( + d3d12->queue.cmd, d3d12->pass[i].rt.handle, D3D12_RESOURCE_STATE_RENDER_TARGET, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); + texture = &d3d12->pass[i].rt; + } + else + { + texture = NULL; + break; + } + } + } + + if (texture) + { + D3D12SetPipelineState(d3d12->queue.cmd, d3d12->pipes[VIDEO_SHADER_STOCK_BLEND]); + D3D12SetGraphicsRootSignature(d3d12->queue.cmd, d3d12->desc.rootSignature); + d3d12_set_texture(d3d12->queue.cmd, &d3d12->frame.texture[0]); + d3d12_set_sampler(d3d12->queue.cmd, d3d12->samplers[RARCH_FILTER_UNSPEC][RARCH_WRAP_DEFAULT]); + D3D12SetGraphicsRootConstantBufferView( + d3d12->queue.cmd, ROOT_ID_UBO, d3d12->frame.ubo_view.BufferLocation); + } + d3d12_resource_transition( d3d12->queue.cmd, d3d12->chain.renderTargets[d3d12->chain.frame_index], D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET); @@ -578,35 +1195,14 @@ static bool d3d12_gfx_frame( d3d12->queue.cmd, d3d12->chain.desc_handles[d3d12->chain.frame_index], d3d12->chain.clearcolor, 0, NULL); - D3D12IASetPrimitiveTopology(d3d12->queue.cmd, D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - if (data && width && height) - { - if (d3d12->frame.texture.desc.Width != width || d3d12->frame.texture.desc.Height != height) - { - d3d12->frame.texture.desc.Width = width; - d3d12->frame.texture.desc.Height = height; - 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); - - d3d12_upload_texture(d3d12->queue.cmd, &d3d12->frame.texture); - } -#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); - D3D12RSSetViewports(d3d12->queue.cmd, 1, &d3d12->frame.viewport); D3D12RSSetScissorRects(d3d12->queue.cmd, 1, &d3d12->frame.scissorRect); - 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->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); + D3D12SetPipelineState(d3d12->queue.cmd, d3d12->pipes[VIDEO_SHADER_STOCK_BLEND]); + D3D12SetGraphicsRootSignature(d3d12->queue.cmd, d3d12->desc.rootSignature); + if (d3d12->menu.enabled && d3d12->menu.texture.handle) { if (d3d12->menu.texture.dirty) @@ -713,13 +1309,14 @@ static bool d3d12_gfx_has_windowed(void* data) return true; } -static bool d3d12_gfx_set_shader(void* data, enum rarch_shader_type type, const char* path) +static struct video_shader* d3d12_gfx_get_current_shader(void* data) { - (void)data; - (void)type; - (void)path; + d3d12_video_t* d3d12 = (d3d12_video_t*)data; - return false; + if (!d3d12) + return NULL; + + return d3d12->shader_preset; } static void d3d12_gfx_viewport_info(void* data, struct video_viewport* vp) @@ -886,7 +1483,7 @@ static const video_poke_interface_t d3d12_poke_interface = { d3d12_gfx_set_osd_msg, NULL, /* show_mouse */ NULL, /* grab_mouse_toggle */ - NULL, /* get_current_shader */ + d3d12_gfx_get_current_shader, NULL, /* get_current_software_framebuffer */ NULL, /* get_hw_render_interface */ }; diff --git a/gfx/video_driver.c b/gfx/video_driver.c index ffa4c310fa..f7ec30896e 100644 --- a/gfx/video_driver.c +++ b/gfx/video_driver.c @@ -599,8 +599,12 @@ static void video_context_driver_reset(void) { const char *video_driver = video_driver_get_ident(); - if(string_is_equal(video_driver, "d3d11")) + if(string_is_equal(video_driver, "d3d10")) + current_video_context_api = GFX_CTX_DIRECT3D10_API; + else if(string_is_equal(video_driver, "d3d11")) current_video_context_api = GFX_CTX_DIRECT3D11_API; + else if(string_is_equal(video_driver, "d3d12")) + current_video_context_api = GFX_CTX_DIRECT3D12_API; else if(string_is_equal(video_driver, "gx2")) current_video_context_api = GFX_CTX_GX2_API; } diff --git a/gfx/video_driver.h b/gfx/video_driver.h index b607b229b2..564225e141 100644 --- a/gfx/video_driver.h +++ b/gfx/video_driver.h @@ -43,7 +43,7 @@ #define RARCH_SCALE_BASE 256 -#if defined(HAVE_CG) || defined(HAVE_HLSL) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_D3D11) +#if defined(HAVE_CG) || defined(HAVE_HLSL) || defined(HAVE_GLSL) || defined(HAVE_SLANG) #ifndef HAVE_SHADER_MANAGER #define HAVE_SHADER_MANAGER #endif @@ -97,7 +97,9 @@ enum gfx_ctx_api GFX_CTX_OPENGL_ES_API, GFX_CTX_DIRECT3D8_API, GFX_CTX_DIRECT3D9_API, + GFX_CTX_DIRECT3D10_API, GFX_CTX_DIRECT3D11_API, + GFX_CTX_DIRECT3D12_API, GFX_CTX_OPENVG_API, GFX_CTX_VULKAN_API, GFX_CTX_GDI_API, diff --git a/gfx/video_shader_parse.c b/gfx/video_shader_parse.c index 227348f68a..348c3d1c61 100644 --- a/gfx/video_shader_parse.c +++ b/gfx/video_shader_parse.c @@ -1162,6 +1162,7 @@ enum rarch_shader_type video_shader_parse_type(const char *path, return shader_type; break; case GFX_CTX_DIRECT3D11_API: + case GFX_CTX_DIRECT3D12_API: case GFX_CTX_VULKAN_API: case GFX_CTX_GX2_API: if (shader_type == RARCH_SHADER_SLANG)