From 4ed2e05870e8307102ac5c8d9d03b964b1a2ffed Mon Sep 17 00:00:00 2001 From: KiritoDv Date: Fri, 23 Jul 2021 14:08:27 -0500 Subject: [PATCH] Removed dx render api and added rumble logo --- bin/title_screen_bg.c | 22 + levels/intro/geo.c | 9 +- src/engine/behavior_script.c | 2 +- src/menu/intro_geo.c | 44 +- src/menu/intro_geo.h | 1 + src/moon/imgui/imgui_impl.cpp | 16 +- src/moon/mod-engine/hooks/hook.h | 3 + src/pc/gfx/gfx_direct3d11.cpp | 754 ------------- src/pc/gfx/gfx_direct3d11.h | 12 - src/pc/gfx/gfx_direct3d12.cpp | 990 ------------------ src/pc/gfx/gfx_direct3d12.h | 12 - src/pc/gfx/gfx_direct3d12_guids.h | 62 -- src/pc/gfx/gfx_direct3d_common.cpp | 313 ------ src/pc/gfx/gfx_direct3d_common.h | 14 - src/pc/gfx/gfx_dxgi.cpp | 641 ------------ src/pc/gfx/gfx_dxgi.h | 16 - src/pc/pc_main.c | 4 - .../controller/rumble_supported.rgba16.png | Bin 0 -> 1945 bytes 18 files changed, 83 insertions(+), 2832 deletions(-) delete mode 100644 src/pc/gfx/gfx_direct3d11.cpp delete mode 100644 src/pc/gfx/gfx_direct3d11.h delete mode 100644 src/pc/gfx/gfx_direct3d12.cpp delete mode 100644 src/pc/gfx/gfx_direct3d12.h delete mode 100644 src/pc/gfx/gfx_direct3d12_guids.h delete mode 100644 src/pc/gfx/gfx_direct3d_common.cpp delete mode 100644 src/pc/gfx/gfx_direct3d_common.h delete mode 100644 src/pc/gfx/gfx_dxgi.cpp delete mode 100644 src/pc/gfx/gfx_dxgi.h create mode 100644 textures/moon/controller/rumble_supported.rgba16.png diff --git a/bin/title_screen_bg.c b/bin/title_screen_bg.c index aae649ac..b57972cb 100644 --- a/bin/title_screen_bg.c +++ b/bin/title_screen_bg.c @@ -106,3 +106,25 @@ const u8 *const game_over_texture_table[] = { }; UNUSED static const u64 title_screen_bg_unused_0 = 0; + +// Texture from Ultra 64 Mario Bros. Project +ALIGNED8 static const u8 title_texture_rumble_pak[] = "textures/moon/controller/rumble_supported.rgba16"; + +Gfx title_screen_bg_dl_0A007548_start[] = { + gsDPPipeSync(), + gsDPSetCycleType(G_CYC_COPY), + gsDPSetTexturePersp(G_TP_NONE), + gsDPSetTextureFilter(G_TF_POINT), + gsDPSetRenderMode(G_RM_NOOP, G_RM_NOOP2), + gsDPLoadTextureTile(title_texture_rumble_pak, G_IM_FMT_RGBA, G_IM_SIZ_16b, 80, 0, 0, 0, 79, 23, 0, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, 7, 5, G_TX_NOLOD, G_TX_NOLOD), + gsSPEndDisplayList(), +}; + +Gfx title_screen_bg_dl_0A007548_end[] = { + gsDPPipeSync(), + gsDPSetCycleType(G_CYC_1CYCLE), + gsDPSetTexturePersp(G_TP_PERSP), + gsDPSetTextureFilter(G_TF_BILERP), + gsDPSetRenderMode(G_RM_AA_ZB_OPA_SURF, G_RM_AA_ZB_OPA_SURF2), + gsSPEndDisplayList(), +}; \ No newline at end of file diff --git a/levels/intro/geo.c b/levels/intro/geo.c index 62fb97b2..5c52d108 100644 --- a/levels/intro/geo.c +++ b/levels/intro/geo.c @@ -91,6 +91,10 @@ const GeoLayout intro_geo_00035C[] = { GEO_ASM(2, geo_draw_mario_head_goddard), GEO_CLOSE_NODE(), GEO_CLOSE_NODE(), + GEO_ZBUFFER(0), + GEO_OPEN_NODE(), + GEO_ASM(0, geo_intro_rumble_pak_graphic), + GEO_CLOSE_NODE(), GEO_CLOSE_NODE(), GEO_END(), }; @@ -113,6 +117,10 @@ const GeoLayout intro_geo_0003B8[] = { GEO_ASM(3, geo_draw_mario_head_goddard), GEO_CLOSE_NODE(), GEO_CLOSE_NODE(), + GEO_ZBUFFER(0), + GEO_OPEN_NODE(), + GEO_ASM(0, geo_intro_rumble_pak_graphic), + GEO_CLOSE_NODE(), GEO_CLOSE_NODE(), GEO_END(), }; @@ -150,4 +158,3 @@ const GeoLayout intro_geo_000414[] = { GEO_CLOSE_NODE(), GEO_END(), }; - diff --git a/src/engine/behavior_script.c b/src/engine/behavior_script.c index 07ba8c04..df9adc16 100644 --- a/src/engine/behavior_script.c +++ b/src/engine/behavior_script.c @@ -152,7 +152,7 @@ static s32 bhv_cmd_cylboard(void) { // Command 0x1B: Sets the current model ID of the object. // Usage: SET_MODEL(modelID) static s32 bhv_cmd_set_model(void) { - u32 modelID = BHV_CMD_GET_U32(0); + u32 modelID = BHV_CMD_GET_2ND_S16(0); gCurrentObject->header.gfx.sharedChild = get_graph_node(modelID); gCurBhvCommand++; return BHV_PROC_CONTINUE; diff --git a/src/menu/intro_geo.c b/src/menu/intro_geo.c index 57297933..48ae8de4 100644 --- a/src/menu/intro_geo.c +++ b/src/menu/intro_geo.c @@ -113,7 +113,7 @@ Gfx *geo_n64_screen(s32 sp50, struct GraphNode *sp54, UNUSED void *context) { displayListIter = displayList; scaleX = 1.0f; scaleY = 1.0f; - scaleZ = 1.0f; + scaleZ = 1.0f; guScale(scaleMat, 0, scaleY, scaleZ); guRotate(scaleMat, 10, 1, 0, 0); guRotate(rotMat, gTitleRotationCounter, 0, 1, 0); @@ -132,7 +132,7 @@ Gfx *geo_n64_screen(s32 sp50, struct GraphNode *sp54, UNUSED void *context) { int range = 80; float step = 1; - if(gTitlePos >= range) + if(gTitlePos >= range) gTitlePingPong = 1; else if (gTitlePos <= -range) gTitlePingPong = 0; @@ -239,7 +239,7 @@ Gfx *intro_backdrop_one_image(s32 index, s8 *backgroundTable) { f32 aspect = GFX_DIMENSIONS_ASPECT_RATIO; int num_tiles_h = (((aspect*SCREEN_HEIGHT)+79)/80); float x_ofs = (SCREEN_WIDTH/2)-(aspect*SCREEN_HEIGHT/2); - + mtx = alloc_display_list(sizeof(*mtx)); displayList = alloc_display_list(36 * sizeof(*displayList)); displayListIter = displayList; @@ -248,8 +248,8 @@ Gfx *intro_backdrop_one_image(s32 index, s8 *backgroundTable) { gSPMatrix(displayListIter++, mtx, G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_PUSH); gSPDisplayList(displayListIter++, &title_screen_bg_dl_0A000118); for (i = 0; i < 4; ++i) { - gDPLoadTextureBlock(displayListIter++, vIntroBgTable[i], G_IM_FMT_RGBA, G_IM_SIZ_16b, 80, 20, 0, - G_TX_CLAMP, G_TX_CLAMP, 7, 6, G_TX_NOLOD, G_TX_NOLOD) + gDPLoadTextureBlock(displayListIter++, vIntroBgTable[i], G_IM_FMT_RGBA, G_IM_SIZ_16b, 80, 20, 0, + G_TX_CLAMP, G_TX_CLAMP, 7, 6, G_TX_NOLOD, G_TX_NOLOD) gSPDisplayList(displayListIter++, introBackgroundDlRows[i]); } gSPPopMatrix(displayListIter++, G_MTX_MODELVIEW); @@ -271,7 +271,7 @@ Gfx *geo_intro_backdrop(s32 sp48, struct GraphNode *sp4c, UNUSED void *context) displayListIter = NULL; f32 aspect = GFX_DIMENSIONS_ASPECT_RATIO; int num_tiles_h = (((aspect*SCREEN_HEIGHT)+79)/80); - + if (sp48 == 1) { displayList = alloc_display_list(((num_tiles_h*3)+4) * sizeof(*displayList)); displayListIter = displayList; @@ -298,7 +298,7 @@ Gfx *geo_game_over_tile(s32 sp40, struct GraphNode *sp44, UNUSED void *context) displayListIter = NULL; f32 aspect = GFX_DIMENSIONS_ASPECT_RATIO; int num_tiles_h = (((aspect*SCREEN_HEIGHT)+79)/80); - + if (sp40 != 1) { gGameOverFrameCounter = 0; gGameOverTableIndex = -2; @@ -335,3 +335,33 @@ Gfx *geo_game_over_tile(s32 sp40, struct GraphNode *sp44, UNUSED void *context) } return displayList; } + +extern Gfx title_screen_bg_dl_0A007548_start[]; +extern Gfx title_screen_bg_dl_0A007548_end[]; + +Gfx *geo_intro_rumble_pak_graphic(s32 state, struct GraphNode *node, UNUSED void *context) { + struct GraphNodeGenerated *genNode = (struct GraphNodeGenerated *)node; + Gfx *dlIter; + Gfx *dl; + s32 introContext; + s8 backgroundTileSix; + u16 left; + dl = NULL; + backgroundTileSix = 0; + + left = GFX_DIMENSIONS_RECT_FROM_RIGHT_EDGE(100); + + if (state != 1) { + dl = NULL; + } else if (state == 1) { + dl = alloc_display_list(6 * sizeof(*dl)); + if (dl != NULL) { + dlIter = dl; + gSPDisplayList(dlIter++, &title_screen_bg_dl_0A007548_start); + gSPTextureRectangle(dlIter++, left << 2, 200 << 2, (left + 79) << 2, (200 + 23) << 2, 7, 0, 0, 4 << 10, 1 << 10); + gSPDisplayList(dlIter++, &title_screen_bg_dl_0A007548_end); + gSPEndDisplayList(dlIter); + } + } + return dl; +} \ No newline at end of file diff --git a/src/menu/intro_geo.h b/src/menu/intro_geo.h index 16b0dd93..0e52bf4b 100644 --- a/src/menu/intro_geo.h +++ b/src/menu/intro_geo.h @@ -15,4 +15,5 @@ Gfx *intro_backdrop_one_image(s32 index, s8 *backgroundTable); Gfx *geo_intro_backdrop(s32 sp48, struct GraphNode *sp4c, UNUSED void *context); Gfx *geo_game_over_tile(s32 sp40, struct GraphNode *sp44, UNUSED void *context); +Gfx *geo_intro_rumble_pak_graphic(s32 state, struct GraphNode *node, UNUSED void *context); #endif // INTRO_GEO_H diff --git a/src/moon/imgui/imgui_impl.cpp b/src/moon/imgui/imgui_impl.cpp index c8b82a61..477bd554 100644 --- a/src/moon/imgui/imgui_impl.cpp +++ b/src/moon/imgui/imgui_impl.cpp @@ -53,10 +53,14 @@ namespace MoonInternal { ImFontConfig font_cfg; font_cfg.FontDataOwnedByAtlas = false; io.Fonts->AddFontFromMemoryTTF((void*) entry->second->data, entry->second->size, 18.f, &font_cfg); - cout << "Loading font: " << entry->first << endl; } ImGui::StyleColorsLightGreen(); io.ConfigWindowsMoveFromTitleBarOnly = true; + MoonInternal::bindHook(IMGUI_API_INIT); + MoonInternal::initBindHook(1, + (struct HookParameter){.name = "io", .parameter = (void*) &io} + ); + MoonInternal::callBindHook(0); window = (SDL_Window*) call.baseArgs["window"]; ImGui_ImplSDL2_InitForOpenGL(window, call.baseArgs["context"]); @@ -78,16 +82,18 @@ namespace MoonInternal { ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplSDL2_NewFrame(window); ImGui::NewFrame(); - - static float f = 0.0f; - static int counter = 0; + MoonInternal::bindHook(IMGUI_API_DRAW); + MoonInternal::initBindHook(0); + MoonInternal::callBindHook(0); if(showWindow){ - ImGui::Begin("Moon64 Game Stats"); + ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0)); + ImGui::Begin("Moon64 Game Stats", NULL, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize); ImGui::Text("Framerate: %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate); ImGui::Text("Branch: " GIT_BRANCH); ImGui::Text("Commit: " GIT_HASH); ImGui::End(); + ImGui::PopStyleColor(); } ImGui::Render(); diff --git a/src/moon/mod-engine/hooks/hook.h b/src/moon/mod-engine/hooks/hook.h index 7f94c440..91c9567d 100644 --- a/src/moon/mod-engine/hooks/hook.h +++ b/src/moon/mod-engine/hooks/hook.h @@ -14,6 +14,9 @@ struct HookParameter { #define SAVE_GRAPH_NODE "SaveGraphNode" #define LOAD_GRAPH_NODE "LoadGraphNode" +#define IMGUI_API_INIT "ImGuiApiInit" +#define IMGUI_API_DRAW "ImGuiApiDraw" + #define WINDOW_API_INIT "WApiInit" #define WINDOW_API_HANDLE_EVENTS "WApiHandleEvents" diff --git a/src/pc/gfx/gfx_direct3d11.cpp b/src/pc/gfx/gfx_direct3d11.cpp deleted file mode 100644 index 73acb605..00000000 --- a/src/pc/gfx/gfx_direct3d11.cpp +++ /dev/null @@ -1,754 +0,0 @@ -#ifdef RAPI_D3D11 - -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#ifndef _LANGUAGE_C -#define _LANGUAGE_C -#endif -#include - -#include "gfx_cc.h" -#include "gfx_window_manager_api.h" -#include "gfx_rendering_api.h" -#include "gfx_direct3d_common.h" - -#define DECLARE_GFX_DXGI_FUNCTIONS -#include "gfx_dxgi.h" - -#include "gfx_screen_config.h" -#include "moon/mod-engine/hooks/hook.h" - -#define THREE_POINT_FILTERING 0 -#define DEBUG_D3D 0 - -using namespace Microsoft::WRL; // For ComPtr - -namespace { - -struct PerFrameCB { - uint32_t noise_frame; - float noise_scale_x; - float noise_scale_y; - uint32_t padding; -}; - -struct PerDrawCB { - struct Texture { - uint32_t width; - uint32_t height; - uint32_t linear_filtering; - uint32_t padding; - } textures[2]; -}; - -struct TextureData { - ComPtr resource_view; - ComPtr sampler_state; - uint32_t width; - uint32_t height; - bool linear_filtering; -}; - -struct ShaderProgramD3D11 { - ComPtr vertex_shader; - ComPtr pixel_shader; - ComPtr input_layout; - ComPtr blend_state; - - uint32_t shader_id; - uint8_t num_inputs; - uint8_t num_floats; - bool used_textures[2]; -}; - -static struct { - HMODULE d3d11_module; - PFN_D3D11_CREATE_DEVICE D3D11CreateDevice; - - HMODULE d3dcompiler_module; - pD3DCompile D3DCompile; - - D3D_FEATURE_LEVEL feature_level; - - ComPtr device; - ComPtr swap_chain; - ComPtr context; - ComPtr backbuffer_view; - ComPtr depth_stencil_view; - ComPtr rasterizer_state; - ComPtr depth_stencil_state; - ComPtr vertex_buffer; - ComPtr per_frame_cb; - ComPtr per_draw_cb; - -#if DEBUG_D3D - ComPtr debug; -#endif - - DXGI_SAMPLE_DESC sample_description; - - PerFrameCB per_frame_cb_data; - PerDrawCB per_draw_cb_data; - - struct ShaderProgramD3D11 shader_program_pool[64]; - uint8_t shader_program_pool_size; - - std::vector textures; - int current_tile; - uint32_t current_texture_ids[2]; - - // Current state - - struct ShaderProgramD3D11 *shader_program; - - uint32_t current_width, current_height; - - int8_t depth_test; - int8_t depth_mask; - int8_t zmode_decal; - - // Previous states (to prevent setting states needlessly) - - struct ShaderProgramD3D11 *last_shader_program = nullptr; - uint32_t last_vertex_buffer_stride = 0; - ComPtr last_blend_state = nullptr; - ComPtr last_resource_views[2] = { nullptr, nullptr }; - ComPtr last_sampler_states[2] = { nullptr, nullptr }; - int8_t last_depth_test = -1; - int8_t last_depth_mask = -1; - int8_t last_zmode_decal = -1; - D3D_PRIMITIVE_TOPOLOGY last_primitive_topology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; -} d3d; - -static LARGE_INTEGER last_time, accumulated_time, frequency; - -static void create_render_target_views(bool is_resize) { - DXGI_SWAP_CHAIN_DESC1 desc1; - - if (is_resize) { - // Release previous stuff (if any) - - d3d.backbuffer_view.Reset(); - d3d.depth_stencil_view.Reset(); - - // Resize swap chain buffers - - ThrowIfFailed(d3d.swap_chain->GetDesc1(&desc1)); - ThrowIfFailed(d3d.swap_chain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, desc1.Flags), - gfx_dxgi_get_h_wnd(), "Failed to resize IDXGISwapChain buffers."); - } - - // Get new size - - ThrowIfFailed(d3d.swap_chain->GetDesc1(&desc1)); - - // Create back buffer - - ComPtr backbuffer_texture; - ThrowIfFailed(d3d.swap_chain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID *) backbuffer_texture.GetAddressOf()), - gfx_dxgi_get_h_wnd(), "Failed to get backbuffer from IDXGISwapChain."); - - ThrowIfFailed(d3d.device->CreateRenderTargetView(backbuffer_texture.Get(), nullptr, d3d.backbuffer_view.GetAddressOf()), - gfx_dxgi_get_h_wnd(), "Failed to create render target view."); - - // Create depth buffer - - D3D11_TEXTURE2D_DESC depth_stencil_texture_desc; - ZeroMemory(&depth_stencil_texture_desc, sizeof(D3D11_TEXTURE2D_DESC)); - - depth_stencil_texture_desc.Width = desc1.Width; - depth_stencil_texture_desc.Height = desc1.Height; - depth_stencil_texture_desc.MipLevels = 1; - depth_stencil_texture_desc.ArraySize = 1; - depth_stencil_texture_desc.Format = d3d.feature_level >= D3D_FEATURE_LEVEL_10_0 ? - DXGI_FORMAT_D32_FLOAT : DXGI_FORMAT_D24_UNORM_S8_UINT; - depth_stencil_texture_desc.SampleDesc = d3d.sample_description; - depth_stencil_texture_desc.Usage = D3D11_USAGE_DEFAULT; - depth_stencil_texture_desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; - depth_stencil_texture_desc.CPUAccessFlags = 0; - depth_stencil_texture_desc.MiscFlags = 0; - - ComPtr depth_stencil_texture; - ThrowIfFailed(d3d.device->CreateTexture2D(&depth_stencil_texture_desc, nullptr, depth_stencil_texture.GetAddressOf())); - ThrowIfFailed(d3d.device->CreateDepthStencilView(depth_stencil_texture.Get(), nullptr, d3d.depth_stencil_view.GetAddressOf())); - - // Save resolution - - d3d.current_width = desc1.Width; - d3d.current_height = desc1.Height; -} - -static void gfx_d3d11_init(void) { - // Load d3d11.dll - d3d.d3d11_module = LoadLibraryW(L"d3d11.dll"); - if (d3d.d3d11_module == nullptr) { - ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError()), gfx_dxgi_get_h_wnd(), "d3d11.dll could not be loaded"); - } - d3d.D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(d3d.d3d11_module, "D3D11CreateDevice"); - - // Load D3DCompiler_47.dll or D3DCompiler_43.dll - d3d.d3dcompiler_module = LoadLibraryW(L"D3DCompiler_47.dll"); - if (d3d.d3dcompiler_module == nullptr) { - d3d.d3dcompiler_module = LoadLibraryW(L"D3DCompiler_43.dll"); - if (d3d.d3dcompiler_module == nullptr) { - ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError()), gfx_dxgi_get_h_wnd(), "D3DCompiler_47.dll or D3DCompiler_43.dll could not be loaded"); - } - } - d3d.D3DCompile = (pD3DCompile)GetProcAddress(d3d.d3dcompiler_module, "D3DCompile"); - - // Create D3D11 device - - gfx_dxgi_create_factory_and_device(DEBUG_D3D, 11, [](IDXGIAdapter1 *adapter, bool test_only) { -#if DEBUG_D3D - UINT device_creation_flags = D3D11_CREATE_DEVICE_DEBUG; -#else - UINT device_creation_flags = 0; -#endif - D3D_FEATURE_LEVEL FeatureLevels[] = { - D3D_FEATURE_LEVEL_11_0, - D3D_FEATURE_LEVEL_10_1, - D3D_FEATURE_LEVEL_10_0, - D3D_FEATURE_LEVEL_9_3, - D3D_FEATURE_LEVEL_9_2, - D3D_FEATURE_LEVEL_9_1 - }; - - HRESULT res = d3d.D3D11CreateDevice( - adapter, - D3D_DRIVER_TYPE_UNKNOWN, // since we use a specific adapter - nullptr, - device_creation_flags, - FeatureLevels, - ARRAYSIZE(FeatureLevels), - D3D11_SDK_VERSION, - test_only ? nullptr : d3d.device.GetAddressOf(), - &d3d.feature_level, - test_only ? nullptr : d3d.context.GetAddressOf()); - - if (test_only) { - return SUCCEEDED(res); - } else { - ThrowIfFailed(res, gfx_dxgi_get_h_wnd(), "Failed to create D3D11 device."); - return true; - } - }); - - // Sample description to be used in back buffer and depth buffer - - d3d.sample_description.Count = 1; - d3d.sample_description.Quality = 0; - - // Create the swap chain - d3d.swap_chain = gfx_dxgi_create_swap_chain(d3d.device.Get()); - - // Create D3D Debug device if in debug mode - -#if DEBUG_D3D - ThrowIfFailed(d3d.device->QueryInterface(__uuidof(ID3D11Debug), (void **) d3d.debug.GetAddressOf()), - gfx_dxgi_get_h_wnd(), "Failed to get ID3D11Debug device."); -#endif - - // Create views - - create_render_target_views(false); - - // Create main vertex buffer - - D3D11_BUFFER_DESC vertex_buffer_desc; - ZeroMemory(&vertex_buffer_desc, sizeof(D3D11_BUFFER_DESC)); - - vertex_buffer_desc.Usage = D3D11_USAGE_DYNAMIC; - vertex_buffer_desc.ByteWidth = 256 * 26 * 3 * sizeof(float); // Same as buf_vbo size in gfx_pc - vertex_buffer_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - vertex_buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - vertex_buffer_desc.MiscFlags = 0; - - ThrowIfFailed(d3d.device->CreateBuffer(&vertex_buffer_desc, nullptr, d3d.vertex_buffer.GetAddressOf()), - gfx_dxgi_get_h_wnd(), "Failed to create vertex buffer."); - - // Create per-frame constant buffer - - D3D11_BUFFER_DESC constant_buffer_desc; - ZeroMemory(&constant_buffer_desc, sizeof(D3D11_BUFFER_DESC)); - - constant_buffer_desc.Usage = D3D11_USAGE_DYNAMIC; - constant_buffer_desc.ByteWidth = sizeof(PerFrameCB); - constant_buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - constant_buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - constant_buffer_desc.MiscFlags = 0; - - ThrowIfFailed(d3d.device->CreateBuffer(&constant_buffer_desc, nullptr, d3d.per_frame_cb.GetAddressOf()), - gfx_dxgi_get_h_wnd(), "Failed to create per-frame constant buffer."); - - d3d.context->PSSetConstantBuffers(0, 1, d3d.per_frame_cb.GetAddressOf()); - - // Create per-draw constant buffer - - constant_buffer_desc.Usage = D3D11_USAGE_DYNAMIC; - constant_buffer_desc.ByteWidth = sizeof(PerDrawCB); - constant_buffer_desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - constant_buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - constant_buffer_desc.MiscFlags = 0; - - ThrowIfFailed(d3d.device->CreateBuffer(&constant_buffer_desc, nullptr, d3d.per_draw_cb.GetAddressOf()), - gfx_dxgi_get_h_wnd(), "Failed to create per-draw constant buffer."); - - d3d.context->PSSetConstantBuffers(1, 1, d3d.per_draw_cb.GetAddressOf()); - - MoonInternal::bindHook(GFX_INIT); - MoonInternal::initBindHook(0); - MoonInternal::callBindHook(1, (struct HookParameter){.name = "d3d", .parameter = (void*) &d3d}); -} - - -static bool gfx_d3d11_z_is_from_0_to_1(void) { - return true; -} - -static void gfx_d3d11_unload_shader(struct ShaderProgram *old_prg) { -} - -static void gfx_d3d11_load_shader(struct ShaderProgram *new_prg) { - d3d.shader_program = (struct ShaderProgramD3D11 *)new_prg; -} - -static struct ShaderProgram *gfx_d3d11_create_and_load_new_shader(uint32_t shader_id) { - CCFeatures cc_features; - gfx_cc_get_features(shader_id, &cc_features); - - char buf[4096]; - size_t len, num_floats; - - gfx_direct3d_common_build_shader(buf, len, num_floats, cc_features, false, THREE_POINT_FILTERING); - - ComPtr vs, ps; - ComPtr error_blob; - -#if DEBUG_D3D - UINT compile_flags = D3DCOMPILE_DEBUG; -#else - UINT compile_flags = D3DCOMPILE_OPTIMIZATION_LEVEL2; -#endif - - HRESULT hr = d3d.D3DCompile(buf, len, nullptr, nullptr, nullptr, "VSMain", "vs_4_0_level_9_1", compile_flags, 0, vs.GetAddressOf(), error_blob.GetAddressOf()); - - if (FAILED(hr)) { - MessageBox(gfx_dxgi_get_h_wnd(), (char *) error_blob->GetBufferPointer(), "Error", MB_OK | MB_ICONERROR); - throw hr; - } - - hr = d3d.D3DCompile(buf, len, nullptr, nullptr, nullptr, "PSMain", "ps_4_0_level_9_1", compile_flags, 0, ps.GetAddressOf(), error_blob.GetAddressOf()); - - if (FAILED(hr)) { - MessageBox(gfx_dxgi_get_h_wnd(), (char *) error_blob->GetBufferPointer(), "Error", MB_OK | MB_ICONERROR); - throw hr; - } - - struct ShaderProgramD3D11 *prg = &d3d.shader_program_pool[d3d.shader_program_pool_size++]; - - ThrowIfFailed(d3d.device->CreateVertexShader(vs->GetBufferPointer(), vs->GetBufferSize(), nullptr, prg->vertex_shader.GetAddressOf())); - ThrowIfFailed(d3d.device->CreatePixelShader(ps->GetBufferPointer(), ps->GetBufferSize(), nullptr, prg->pixel_shader.GetAddressOf())); - - // Input Layout - - D3D11_INPUT_ELEMENT_DESC ied[7]; - uint8_t ied_index = 0; - ied[ied_index++] = { "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }; - if (cc_features.used_textures[0] || cc_features.used_textures[1]) { - ied[ied_index++] = { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }; - } - if (cc_features.opt_fog) { - ied[ied_index++] = { "FOG", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }; - } - for (unsigned int i = 0; i < cc_features.num_inputs; i++) { - DXGI_FORMAT format = cc_features.opt_alpha ? DXGI_FORMAT_R32G32B32A32_FLOAT : DXGI_FORMAT_R32G32B32_FLOAT; - ied[ied_index++] = { "INPUT", i, format, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }; - } - - ThrowIfFailed(d3d.device->CreateInputLayout(ied, ied_index, vs->GetBufferPointer(), vs->GetBufferSize(), prg->input_layout.GetAddressOf())); - - // Blend state - - D3D11_BLEND_DESC blend_desc; - ZeroMemory(&blend_desc, sizeof(D3D11_BLEND_DESC)); - - if (cc_features.opt_alpha) { - blend_desc.RenderTarget[0].BlendEnable = true; - blend_desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; - blend_desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; - blend_desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; - blend_desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; - blend_desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; - blend_desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; - blend_desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; - } else { - blend_desc.RenderTarget[0].BlendEnable = false; - blend_desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; - } - - ThrowIfFailed(d3d.device->CreateBlendState(&blend_desc, prg->blend_state.GetAddressOf())); - - // Save some values - - prg->shader_id = shader_id; - prg->num_inputs = cc_features.num_inputs; - prg->num_floats = num_floats; - prg->used_textures[0] = cc_features.used_textures[0]; - prg->used_textures[1] = cc_features.used_textures[1]; - - return (struct ShaderProgram *)(d3d.shader_program = prg); -} - -static struct ShaderProgram *gfx_d3d11_lookup_shader(uint32_t shader_id) { - for (size_t i = 0; i < d3d.shader_program_pool_size; i++) { - if (d3d.shader_program_pool[i].shader_id == shader_id) { - return (struct ShaderProgram *)&d3d.shader_program_pool[i]; - } - } - return nullptr; -} - -static void gfx_d3d11_shader_get_info(struct ShaderProgram *prg, uint8_t *num_inputs, bool used_textures[2]) { - struct ShaderProgramD3D11 *p = (struct ShaderProgramD3D11 *)prg; - - *num_inputs = p->num_inputs; - used_textures[0] = p->used_textures[0]; - used_textures[1] = p->used_textures[1]; -} - -static uint32_t gfx_d3d11_new_texture(void) { - d3d.textures.resize(d3d.textures.size() + 1); - return (uint32_t)(d3d.textures.size() - 1); -} - -static void gfx_d3d11_select_texture(int tile, uint32_t texture_id) { - d3d.current_tile = tile; - d3d.current_texture_ids[tile] = texture_id; -} - -static D3D11_TEXTURE_ADDRESS_MODE gfx_cm_to_d3d11(uint32_t val) { - if (val & G_TX_CLAMP) { - return D3D11_TEXTURE_ADDRESS_CLAMP; - } - return (val & G_TX_MIRROR) ? D3D11_TEXTURE_ADDRESS_MIRROR : D3D11_TEXTURE_ADDRESS_WRAP; -} - -static void gfx_d3d11_upload_texture(const uint8_t *rgba32_buf, int width, int height) { - // Create texture - - D3D11_TEXTURE2D_DESC texture_desc; - ZeroMemory(&texture_desc, sizeof(D3D11_TEXTURE2D_DESC)); - - texture_desc.Width = width; - texture_desc.Height = height; - texture_desc.Usage = D3D11_USAGE_IMMUTABLE; - texture_desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texture_desc.CPUAccessFlags = 0; - texture_desc.MiscFlags = 0; // D3D11_RESOURCE_MISC_GENERATE_MIPS ? - texture_desc.ArraySize = 1; - texture_desc.MipLevels = 1; - texture_desc.SampleDesc.Count = 1; - texture_desc.SampleDesc.Quality = 0; - - D3D11_SUBRESOURCE_DATA resource_data; - resource_data.pSysMem = rgba32_buf; - resource_data.SysMemPitch = width * 4; - resource_data.SysMemSlicePitch = resource_data.SysMemPitch * height; - - ComPtr texture; - ThrowIfFailed(d3d.device->CreateTexture2D(&texture_desc, &resource_data, texture.GetAddressOf())); - - // Create shader resource view from texture - - D3D11_SHADER_RESOURCE_VIEW_DESC resource_view_desc; - ZeroMemory(&resource_view_desc, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC)); - - resource_view_desc.Format = texture_desc.Format; - resource_view_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - resource_view_desc.Texture2D.MostDetailedMip = 0; - resource_view_desc.Texture2D.MipLevels = -1; - - TextureData *texture_data = &d3d.textures[d3d.current_texture_ids[d3d.current_tile]]; - texture_data->width = width; - texture_data->height = height; - - if (texture_data->resource_view.Get() != nullptr) { - // Free the previous texture in this slot - texture_data->resource_view.Reset(); - } - - ThrowIfFailed(d3d.device->CreateShaderResourceView(texture.Get(), &resource_view_desc, texture_data->resource_view.GetAddressOf())); -} - -static void gfx_d3d11_set_sampler_parameters(int tile, bool linear_filter, uint32_t cms, uint32_t cmt) { - D3D11_SAMPLER_DESC sampler_desc; - ZeroMemory(&sampler_desc, sizeof(D3D11_SAMPLER_DESC)); - -#if THREE_POINT_FILTERING - sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; -#else - sampler_desc.Filter = linear_filter ? D3D11_FILTER_MIN_MAG_MIP_LINEAR : D3D11_FILTER_MIN_MAG_MIP_POINT; -#endif - sampler_desc.AddressU = gfx_cm_to_d3d11(cms); - sampler_desc.AddressV = gfx_cm_to_d3d11(cmt); - sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; - sampler_desc.MinLOD = 0; - sampler_desc.MaxLOD = D3D11_FLOAT32_MAX; - - TextureData *texture_data = &d3d.textures[d3d.current_texture_ids[tile]]; - texture_data->linear_filtering = linear_filter; - - // This function is called twice per texture, the first one only to set default values. - // Maybe that could be skipped? Anyway, make sure to release the first default sampler - // state before setting the actual one. - texture_data->sampler_state.Reset(); - - ThrowIfFailed(d3d.device->CreateSamplerState(&sampler_desc, texture_data->sampler_state.GetAddressOf())); -} - -static void gfx_d3d11_set_depth_test(bool depth_test) { - d3d.depth_test = depth_test; -} - -static void gfx_d3d11_set_depth_mask(bool depth_mask) { - d3d.depth_mask = depth_mask; -} - -static void gfx_d3d11_set_zmode_decal(bool zmode_decal) { - d3d.zmode_decal = zmode_decal; -} - -static void gfx_d3d11_set_viewport(int x, int y, int width, int height) { - D3D11_VIEWPORT viewport; - viewport.TopLeftX = x; - viewport.TopLeftY = d3d.current_height - y - height; - viewport.Width = width; - viewport.Height = height; - viewport.MinDepth = 0.0f; - viewport.MaxDepth = 1.0f; - - d3d.context->RSSetViewports(1, &viewport); -} - -static void gfx_d3d11_set_scissor(int x, int y, int width, int height) { - D3D11_RECT rect; - rect.left = x; - rect.top = d3d.current_height - y - height; - rect.right = x + width; - rect.bottom = d3d.current_height - y; - - d3d.context->RSSetScissorRects(1, &rect); -} - -static void gfx_d3d11_set_use_alpha(bool use_alpha) { - // Already part of the pipeline state from shader info -} - -static void gfx_d3d11_draw_triangles(float buf_vbo[], size_t buf_vbo_len, size_t buf_vbo_num_tris) { - - if (d3d.last_depth_test != d3d.depth_test || d3d.last_depth_mask != d3d.depth_mask) { - d3d.last_depth_test = d3d.depth_test; - d3d.last_depth_mask = d3d.depth_mask; - - d3d.depth_stencil_state.Reset(); - - D3D11_DEPTH_STENCIL_DESC depth_stencil_desc; - ZeroMemory(&depth_stencil_desc, sizeof(D3D11_DEPTH_STENCIL_DESC)); - - depth_stencil_desc.DepthEnable = d3d.depth_test; - depth_stencil_desc.DepthWriteMask = d3d.depth_mask ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO; - depth_stencil_desc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL; - depth_stencil_desc.StencilEnable = false; - - ThrowIfFailed(d3d.device->CreateDepthStencilState(&depth_stencil_desc, d3d.depth_stencil_state.GetAddressOf())); - d3d.context->OMSetDepthStencilState(d3d.depth_stencil_state.Get(), 0); - } - - if (d3d.last_zmode_decal != d3d.zmode_decal) { - d3d.last_zmode_decal = d3d.zmode_decal; - - d3d.rasterizer_state.Reset(); - - D3D11_RASTERIZER_DESC rasterizer_desc; - ZeroMemory(&rasterizer_desc, sizeof(D3D11_RASTERIZER_DESC)); - - rasterizer_desc.FillMode = D3D11_FILL_SOLID; - rasterizer_desc.CullMode = D3D11_CULL_NONE; - rasterizer_desc.FrontCounterClockwise = true; - rasterizer_desc.DepthBias = 0; - rasterizer_desc.SlopeScaledDepthBias = d3d.zmode_decal ? -2.0f : 0.0f; - rasterizer_desc.DepthBiasClamp = 0.0f; - rasterizer_desc.DepthClipEnable = true; - rasterizer_desc.ScissorEnable = true; - rasterizer_desc.MultisampleEnable = false; - rasterizer_desc.AntialiasedLineEnable = false; - - ThrowIfFailed(d3d.device->CreateRasterizerState(&rasterizer_desc, d3d.rasterizer_state.GetAddressOf())); - d3d.context->RSSetState(d3d.rasterizer_state.Get()); - } - - bool textures_changed = false; - - for (int i = 0; i < 2; i++) { - if (d3d.shader_program->used_textures[i]) { - if (d3d.last_resource_views[i].Get() != d3d.textures[d3d.current_texture_ids[i]].resource_view.Get()) { - d3d.last_resource_views[i] = d3d.textures[d3d.current_texture_ids[i]].resource_view.Get(); - d3d.context->PSSetShaderResources(i, 1, d3d.textures[d3d.current_texture_ids[i]].resource_view.GetAddressOf()); - -#if THREE_POINT_FILTERING - d3d.per_draw_cb_data.textures[i].width = d3d.textures[d3d.current_texture_ids[i]].width; - d3d.per_draw_cb_data.textures[i].height = d3d.textures[d3d.current_texture_ids[i]].height; - d3d.per_draw_cb_data.textures[i].linear_filtering = d3d.textures[d3d.current_texture_ids[i]].linear_filtering; - textures_changed = true; -#endif - - if (d3d.last_sampler_states[i].Get() != d3d.textures[d3d.current_texture_ids[i]].sampler_state.Get()) { - d3d.last_sampler_states[i] = d3d.textures[d3d.current_texture_ids[i]].sampler_state.Get(); - d3d.context->PSSetSamplers(i, 1, d3d.textures[d3d.current_texture_ids[i]].sampler_state.GetAddressOf()); - } - } - } - } - - // Set per-draw constant buffer - - if (textures_changed) { - D3D11_MAPPED_SUBRESOURCE ms; - ZeroMemory(&ms, sizeof(D3D11_MAPPED_SUBRESOURCE)); - d3d.context->Map(d3d.per_draw_cb.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &ms); - memcpy(ms.pData, &d3d.per_draw_cb_data, sizeof(PerDrawCB)); - d3d.context->Unmap(d3d.per_draw_cb.Get(), 0); - } - - // Set vertex buffer data - - D3D11_MAPPED_SUBRESOURCE ms; - ZeroMemory(&ms, sizeof(D3D11_MAPPED_SUBRESOURCE)); - d3d.context->Map(d3d.vertex_buffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &ms); - memcpy(ms.pData, buf_vbo, buf_vbo_len * sizeof(float)); - d3d.context->Unmap(d3d.vertex_buffer.Get(), 0); - - uint32_t stride = d3d.shader_program->num_floats * sizeof(float); - uint32_t offset = 0; - - if (d3d.last_vertex_buffer_stride != stride) { - d3d.last_vertex_buffer_stride = stride; - d3d.context->IASetVertexBuffers(0, 1, d3d.vertex_buffer.GetAddressOf(), &stride, &offset); - } - - if (d3d.last_shader_program != d3d.shader_program) { - d3d.last_shader_program = d3d.shader_program; - d3d.context->IASetInputLayout(d3d.shader_program->input_layout.Get()); - d3d.context->VSSetShader(d3d.shader_program->vertex_shader.Get(), 0, 0); - d3d.context->PSSetShader(d3d.shader_program->pixel_shader.Get(), 0, 0); - - if (d3d.last_blend_state.Get() != d3d.shader_program->blend_state.Get()) { - d3d.last_blend_state = d3d.shader_program->blend_state.Get(); - d3d.context->OMSetBlendState(d3d.shader_program->blend_state.Get(), 0, 0xFFFFFFFF); - } - } - - if (d3d.last_primitive_topology != D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST) { - d3d.last_primitive_topology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; - d3d.context->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - } - - d3d.context->Draw(buf_vbo_num_tris * 3, 0); -} - -static void gfx_d3d11_on_resize(void) { - create_render_target_views(true); - MoonInternal::bindHook(GFX_ON_REZISE); - MoonInternal::initBindHook(0); - MoonInternal::callBindHook(1, (struct HookParameter){.name = "d3d", .parameter = (void*) &d3d}); -} - -static void gfx_d3d11_start_frame(void) { - MoonInternal::bindHook(GFX_PRE_START_FRAME); - MoonInternal::initBindHook(0); - if(MoonInternal::callBindHook(1, (struct HookParameter){.name = "d3d", .parameter = (void*) &d3d})) return; - - // Set render targets - - d3d.context->OMSetRenderTargets(1, d3d.backbuffer_view.GetAddressOf(), d3d.depth_stencil_view.Get()); - - // Clear render targets - - const float clearColor[] = { 0.0f, 0.0f, 0.0f, 1.0f }; - d3d.context->ClearRenderTargetView(d3d.backbuffer_view.Get(), clearColor); - d3d.context->ClearDepthStencilView(d3d.depth_stencil_view.Get(), D3D11_CLEAR_DEPTH, 1.0f, 0); - - // Set per-frame constant buffer - - d3d.per_frame_cb_data.noise_frame++; - if (d3d.per_frame_cb_data.noise_frame > 150) { - // No high values, as noise starts to look ugly - d3d.per_frame_cb_data.noise_frame = 0; - } - - d3d.per_frame_cb_data.noise_scale_x = (float) d3d.current_width; - d3d.per_frame_cb_data.noise_scale_y = (float) d3d.current_height; - - D3D11_MAPPED_SUBRESOURCE ms; - ZeroMemory(&ms, sizeof(D3D11_MAPPED_SUBRESOURCE)); - d3d.context->Map(d3d.per_frame_cb.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &ms); - memcpy(ms.pData, &d3d.per_frame_cb_data, sizeof(PerFrameCB)); - d3d.context->Unmap(d3d.per_frame_cb.Get(), 0); - - MoonInternal::bindHook(GFX_POST_START_FRAME); - MoonInternal::initBindHook(0); - MoonInternal::callBindHook(1, (struct HookParameter){.name = "d3d", .parameter = (void*) &d3d}); -} - -static void gfx_d3d11_end_frame(void) { - MoonInternal::bindHook(GFX_PRE_END_FRAME); - MoonInternal::initBindHook(0); - MoonInternal::callBindHook(1, (struct HookParameter){.name = "d3d", .parameter = (void*) &d3d}); - - MoonInternal::bindHook(GFX_POST_END_FRAME); - MoonInternal::initBindHook(0); - MoonInternal::callBindHook(1, (struct HookParameter){.name = "d3d", .parameter = (void*) &d3d}); -} - -static void gfx_d3d11_finish_render(void) { -} - -} // namespace - -struct GfxRenderingAPI gfx_direct3d11_api = { - gfx_d3d11_z_is_from_0_to_1, - gfx_d3d11_unload_shader, - gfx_d3d11_load_shader, - gfx_d3d11_create_and_load_new_shader, - gfx_d3d11_lookup_shader, - gfx_d3d11_shader_get_info, - gfx_d3d11_new_texture, - gfx_d3d11_select_texture, - gfx_d3d11_upload_texture, - gfx_d3d11_set_sampler_parameters, - gfx_d3d11_set_depth_test, - gfx_d3d11_set_depth_mask, - gfx_d3d11_set_zmode_decal, - gfx_d3d11_set_viewport, - gfx_d3d11_set_scissor, - gfx_d3d11_set_use_alpha, - gfx_d3d11_draw_triangles, - gfx_d3d11_init, - gfx_d3d11_on_resize, - gfx_d3d11_start_frame, - gfx_d3d11_end_frame, - gfx_d3d11_finish_render -}; - -#endif diff --git a/src/pc/gfx/gfx_direct3d11.h b/src/pc/gfx/gfx_direct3d11.h deleted file mode 100644 index 5d795602..00000000 --- a/src/pc/gfx/gfx_direct3d11.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifdef RAPI_D3D11 - -#ifndef GFX_DIRECT3D11_H -#define GFX_DIRECT3D11_H - -#include "gfx_rendering_api.h" - -extern struct GfxRenderingAPI gfx_direct3d11_api; - -#endif - -#endif diff --git a/src/pc/gfx/gfx_direct3d12.cpp b/src/pc/gfx/gfx_direct3d12.cpp deleted file mode 100644 index c8913a93..00000000 --- a/src/pc/gfx/gfx_direct3d12.cpp +++ /dev/null @@ -1,990 +0,0 @@ -#ifdef RAPI_D3D12 - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -// This is needed when compiling with MinGW, used in d3d12.h -#define __in_ecount_opt(size) - -#include -#include -#include "dxsdk/d3d12.h" -#include - -#include "gfx_direct3d12_guids.h" - -#include "dxsdk/d3dx12.h" - -#ifndef _LANGUAGE_C -#define _LANGUAGE_C -#endif -#include - -#define DECLARE_GFX_DXGI_FUNCTIONS -#include "gfx_dxgi.h" - -#include "gfx_cc.h" -#include "gfx_window_manager_api.h" -#include "gfx_rendering_api.h" -#include "gfx_direct3d_common.h" - -#include "gfx_screen_config.h" -#include "moon/mod-engine/hooks/hook.h" - -#define DEBUG_D3D 0 - -using namespace Microsoft::WRL; // For ComPtr - -namespace { - -struct ShaderProgramD3D12 { - uint32_t shader_id; - uint8_t num_inputs; - bool used_textures[2]; - uint8_t num_floats; - uint8_t num_attribs; - - ComPtr vertex_shader; - ComPtr pixel_shader; - ComPtr root_signature; -}; - -struct PipelineDesc { - uint32_t shader_id; - bool depth_test; - bool depth_mask; - bool zmode_decal; - bool _padding; - - bool operator==(const PipelineDesc& o) const { - return memcmp(this, &o, sizeof(*this)) == 0; - } - - bool operator<(const PipelineDesc& o) const { - return memcmp(this, &o, sizeof(*this)) < 0; - } -}; - -struct TextureHeap { - ComPtr heap; - std::vector free_list; -}; - -struct TextureData { - ComPtr resource; - struct TextureHeap *heap; - uint8_t heap_offset; - - uint64_t last_frame_counter; - uint32_t descriptor_index; - int sampler_parameters; -}; - -struct NoiseCB { - uint32_t noise_frame; - float noise_scale_x; - float noise_scale_y; - uint32_t padding; -}; - -static struct { - HMODULE d3d12_module; - PFN_D3D12_CREATE_DEVICE D3D12CreateDevice; - PFN_D3D12_GET_DEBUG_INTERFACE D3D12GetDebugInterface; - - HMODULE d3dcompiler_module; - pD3DCompile D3DCompile; - - struct ShaderProgramD3D12 shader_program_pool[64]; - uint8_t shader_program_pool_size; - - uint32_t current_width, current_height; - - ComPtr device; - ComPtr command_queue; - ComPtr copy_command_queue; - ComPtr swap_chain; - ComPtr rtv_heap; - UINT rtv_descriptor_size; - ComPtr render_targets[2]; - ComPtr command_allocator; - ComPtr copy_command_allocator; - ComPtr command_list; - ComPtr copy_command_list; - ComPtr dsv_heap; - ComPtr depth_stencil_buffer; - ComPtr srv_heap; - UINT srv_descriptor_size; - ComPtr sampler_heap; - UINT sampler_descriptor_size; - - std::map, std::list> texture_heaps; - - std::map>> upload_heaps; - std::vector>> upload_heaps_in_flight; - ComPtr copy_fence; - uint64_t copy_fence_value; - - std::vector textures; - int current_tile; - uint32_t current_texture_ids[2]; - uint32_t srv_pos; - - int frame_index; - ComPtr fence; - HANDLE fence_event; - - uint64_t frame_counter; - - ComPtr noise_cb; - void *mapped_noise_cb_address; - struct NoiseCB noise_cb_data; - - ComPtr vertex_buffer; - void *mapped_vbuf_address; - int vbuf_pos; - - std::vector> resources_to_clean_at_end_of_frame; - std::vector> texture_heap_allocations_to_reclaim_at_end_of_frame; - - std::map> pipeline_states; - bool must_reload_pipeline; - - // Current state: - ID3D12PipelineState *pipeline_state; - struct ShaderProgramD3D12 *shader_program; - bool depth_test; - bool depth_mask; - bool zmode_decal; - - CD3DX12_VIEWPORT viewport; - CD3DX12_RECT scissor; -} d3d; - -static int texture_uploads = 0; -static int max_texture_uploads; - -static D3D12_CPU_DESCRIPTOR_HANDLE get_cpu_descriptor_handle(ComPtr& heap) { -#ifdef __MINGW32__ - // We would like to do this: - // D3D12_CPU_DESCRIPTOR_HANDLE handle = heap->GetCPUDescriptorHandleForHeapStart(); - // but MinGW64 doesn't follow the calling conventions of VC++ for some reason. - // Per MS documentation "User-defined types can be returned by value from global functions and static member functions"... - // "Otherwise, the caller assumes the responsibility of allocating memory and passing a pointer for the return value as the first argument". - // The method here is a non-static member function, and hence we need to pass the address to the return value as a parameter. - // MinGW32 has the same issue. - auto fn = heap->GetCPUDescriptorHandleForHeapStart; - void (STDMETHODCALLTYPE ID3D12DescriptorHeap::*fun)(D3D12_CPU_DESCRIPTOR_HANDLE *out) = (void (STDMETHODCALLTYPE ID3D12DescriptorHeap::*)(D3D12_CPU_DESCRIPTOR_HANDLE *out))fn; - D3D12_CPU_DESCRIPTOR_HANDLE handle; - (heap.Get()->*fun)(&handle); - return handle; -#else - return heap->GetCPUDescriptorHandleForHeapStart(); -#endif -} - -static D3D12_GPU_DESCRIPTOR_HANDLE get_gpu_descriptor_handle(ComPtr& heap) { -#ifdef __MINGW32__ - // See get_cpu_descriptor_handle - auto fn = heap->GetGPUDescriptorHandleForHeapStart; - void (STDMETHODCALLTYPE ID3D12DescriptorHeap::*fun)(D3D12_GPU_DESCRIPTOR_HANDLE *out) = (void (STDMETHODCALLTYPE ID3D12DescriptorHeap::*)(D3D12_GPU_DESCRIPTOR_HANDLE *out))fn; - D3D12_GPU_DESCRIPTOR_HANDLE handle; - (heap.Get()->*fun)(&handle); - return handle; -#else - return heap->GetGPUDescriptorHandleForHeapStart(); -#endif -} - -static D3D12_RESOURCE_ALLOCATION_INFO get_resource_allocation_info(const D3D12_RESOURCE_DESC *resource_desc) { -#ifdef __MINGW32__ - // See get_cpu_descriptor_handle - auto fn = d3d.device->GetResourceAllocationInfo; - void (STDMETHODCALLTYPE ID3D12Device::*fun)(D3D12_RESOURCE_ALLOCATION_INFO *out, UINT visibleMask, UINT numResourceDescs, const D3D12_RESOURCE_DESC *pResourceDescs) = - (void (STDMETHODCALLTYPE ID3D12Device::*)(D3D12_RESOURCE_ALLOCATION_INFO *out, UINT visibleMask, UINT numResourceDescs, const D3D12_RESOURCE_DESC *pResourceDescs))fn; - D3D12_RESOURCE_ALLOCATION_INFO out; - (d3d.device.Get()->*fun)(&out, 0, 1, resource_desc); - return out; -#else - return d3d.device->GetResourceAllocationInfo(0, 1, resource_desc); -#endif -} - -static bool gfx_direct3d12_z_is_from_0_to_1(void) { - return true; -} - -static void gfx_direct3d12_unload_shader(struct ShaderProgram *old_prg) { -} - -static void gfx_direct3d12_load_shader(struct ShaderProgram *new_prg) { - d3d.shader_program = (struct ShaderProgramD3D12 *)new_prg; - d3d.must_reload_pipeline = true; -} - -static struct ShaderProgram *gfx_direct3d12_create_and_load_new_shader(uint32_t shader_id) { - /*static FILE *fp; - if (!fp) { - fp = fopen("shaders.txt", "w"); - } - fprintf(fp, "0x%08x\n", shader_id); - fflush(fp);*/ - - struct ShaderProgramD3D12 *prg = &d3d.shader_program_pool[d3d.shader_program_pool_size++]; - - CCFeatures cc_features; - gfx_cc_get_features(shader_id, &cc_features); - - char buf[2048]; - size_t len, num_floats; - - gfx_direct3d_common_build_shader(buf, len, num_floats, cc_features, true, false); - - //fwrite(buf, 1, len, stdout); - - ThrowIfFailed(d3d.D3DCompile(buf, len, nullptr, nullptr, nullptr, "VSMain", "vs_5_1", D3DCOMPILE_OPTIMIZATION_LEVEL3, 0, &prg->vertex_shader, nullptr)); - ThrowIfFailed(d3d.D3DCompile(buf, len, nullptr, nullptr, nullptr, "PSMain", "ps_5_1", D3DCOMPILE_OPTIMIZATION_LEVEL3, 0, &prg->pixel_shader, nullptr)); - - ThrowIfFailed(d3d.device->CreateRootSignature(0, prg->pixel_shader->GetBufferPointer(), prg->pixel_shader->GetBufferSize(), IID_PPV_ARGS(&prg->root_signature))); - - prg->shader_id = shader_id; - prg->num_inputs = cc_features.num_inputs; - prg->used_textures[0] = cc_features.used_textures[0]; - prg->used_textures[1] = cc_features.used_textures[1]; - prg->num_floats = num_floats; - //prg->num_attribs = cnt; - - d3d.must_reload_pipeline = true; - return (struct ShaderProgram *)(d3d.shader_program = prg); -} - -static struct ShaderProgram *gfx_direct3d12_lookup_shader(uint32_t shader_id) { - for (size_t i = 0; i < d3d.shader_program_pool_size; i++) { - if (d3d.shader_program_pool[i].shader_id == shader_id) { - return (struct ShaderProgram *)&d3d.shader_program_pool[i]; - } - } - return nullptr; -} - -static void gfx_direct3d12_shader_get_info(struct ShaderProgram *prg, uint8_t *num_inputs, bool used_textures[2]) { - struct ShaderProgramD3D12 *p = (struct ShaderProgramD3D12 *)prg; - - *num_inputs = p->num_inputs; - used_textures[0] = p->used_textures[0]; - used_textures[1] = p->used_textures[1]; -} - -static uint32_t gfx_direct3d12_new_texture(void) { - d3d.textures.resize(d3d.textures.size() + 1); - return (uint32_t)(d3d.textures.size() - 1); -} - -static void gfx_direct3d12_select_texture(int tile, uint32_t texture_id) { - d3d.current_tile = tile; - d3d.current_texture_ids[tile] = texture_id; -} - -static void gfx_direct3d12_upload_texture(const uint8_t *rgba32_buf, int width, int height) { - texture_uploads++; - - ComPtr texture_resource; - - // Describe and create a Texture2D. - D3D12_RESOURCE_DESC texture_desc = {}; - texture_desc.MipLevels = 1; - texture_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - texture_desc.Width = width; - texture_desc.Height = height; - texture_desc.Flags = D3D12_RESOURCE_FLAG_NONE; - texture_desc.DepthOrArraySize = 1; - texture_desc.SampleDesc.Count = 1; - texture_desc.SampleDesc.Quality = 0; - texture_desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; - texture_desc.Alignment = ((width + 31) / 32) * ((height + 31) / 32) > 16 ? 0 : D3D12_SMALL_RESOURCE_PLACEMENT_ALIGNMENT; - - D3D12_RESOURCE_ALLOCATION_INFO alloc_info = get_resource_allocation_info(&texture_desc); - - std::list& heaps = d3d.texture_heaps[std::pair(alloc_info.SizeInBytes, alloc_info.Alignment)]; - - struct TextureHeap *found_heap = nullptr; - for (struct TextureHeap& heap : heaps) { - if (!heap.free_list.empty()) { - found_heap = &heap; - } - } - if (found_heap == nullptr) { - heaps.resize(heaps.size() + 1); - found_heap = &heaps.back(); - - // In case of HD textures, make sure too much memory isn't wasted - int textures_per_heap = 524288 / alloc_info.SizeInBytes; - if (textures_per_heap < 1) { - textures_per_heap = 1; - } else if (textures_per_heap > 64) { - textures_per_heap = 64; - } - - D3D12_HEAP_DESC heap_desc = {}; - heap_desc.SizeInBytes = alloc_info.SizeInBytes * textures_per_heap; - if (alloc_info.Alignment == D3D12_SMALL_RESOURCE_PLACEMENT_ALIGNMENT) { - heap_desc.Alignment = D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT; - } else { - heap_desc.Alignment = alloc_info.Alignment; - } - heap_desc.Properties.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; - heap_desc.Properties.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; - heap_desc.Properties.Type = D3D12_HEAP_TYPE_DEFAULT; - heap_desc.Flags = D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES; - ThrowIfFailed(d3d.device->CreateHeap(&heap_desc, IID_PPV_ARGS(&found_heap->heap))); - for (int i = 0; i < textures_per_heap; i++) { - found_heap->free_list.push_back(i); - } - } - - uint8_t heap_offset = found_heap->free_list.back(); - found_heap->free_list.pop_back(); - ThrowIfFailed(d3d.device->CreatePlacedResource(found_heap->heap.Get(), heap_offset * alloc_info.SizeInBytes, &texture_desc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr, IID_PPV_ARGS(&texture_resource))); - - D3D12_PLACED_SUBRESOURCE_FOOTPRINT layout; - UINT num_rows; - UINT64 row_size_in_bytes; - UINT64 upload_buffer_size; - d3d.device->GetCopyableFootprints(&texture_desc, 0, 1, 0, &layout, &num_rows, &row_size_in_bytes, &upload_buffer_size); - - std::vector>& upload_heaps = d3d.upload_heaps[upload_buffer_size]; - ComPtr upload_heap; - if (upload_heaps.empty()) { - CD3DX12_HEAP_PROPERTIES hp(D3D12_HEAP_TYPE_UPLOAD); - CD3DX12_RESOURCE_DESC rdb = CD3DX12_RESOURCE_DESC::Buffer(upload_buffer_size); - ThrowIfFailed(d3d.device->CreateCommittedResource( - &hp, - D3D12_HEAP_FLAG_NONE, - &rdb, - D3D12_RESOURCE_STATE_GENERIC_READ, - nullptr, - IID_PPV_ARGS(&upload_heap))); - } else { - upload_heap = upload_heaps.back(); - upload_heaps.pop_back(); - } - - { - D3D12_SUBRESOURCE_DATA texture_data = {}; - texture_data.pData = rgba32_buf; - texture_data.RowPitch = width * 4; // RGBA - texture_data.SlicePitch = texture_data.RowPitch * height; - - void *data; - upload_heap->Map(0, nullptr, &data); - D3D12_MEMCPY_DEST dest_data = { (uint8_t *)data + layout.Offset, layout.Footprint.RowPitch, SIZE_T(layout.Footprint.RowPitch) * SIZE_T(num_rows) }; - MemcpySubresource(&dest_data, &texture_data, static_cast(row_size_in_bytes), num_rows, layout.Footprint.Depth); - upload_heap->Unmap(0, nullptr); - - CD3DX12_TEXTURE_COPY_LOCATION dst(texture_resource.Get(), 0); - CD3DX12_TEXTURE_COPY_LOCATION src(upload_heap.Get(), layout); - d3d.copy_command_list->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr); - } - - CD3DX12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition(texture_resource.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE); - d3d.command_list->ResourceBarrier(1, &barrier); - - d3d.upload_heaps_in_flight.push_back(std::make_pair((size_t)upload_buffer_size, std::move(upload_heap))); - - struct TextureData& td = d3d.textures[d3d.current_texture_ids[d3d.current_tile]]; - if (td.resource.Get() != nullptr) { - d3d.resources_to_clean_at_end_of_frame.push_back(std::move(td.resource)); - d3d.texture_heap_allocations_to_reclaim_at_end_of_frame.push_back(std::make_pair(td.heap, td.heap_offset)); - td.last_frame_counter = 0; - } - td.resource = std::move(texture_resource); - td.heap = found_heap; - td.heap_offset = heap_offset; -} - -static int gfx_cm_to_index(uint32_t val) { - if (val & G_TX_CLAMP) { - return 2; - } - return (val & G_TX_MIRROR) ? 1 : 0; -} - -static void gfx_direct3d12_set_sampler_parameters(int tile, bool linear_filter, uint32_t cms, uint32_t cmt) { - d3d.textures[d3d.current_texture_ids[tile]].sampler_parameters = linear_filter * 9 + gfx_cm_to_index(cms) * 3 + gfx_cm_to_index(cmt); -} - -static void gfx_direct3d12_set_depth_test(bool depth_test) { - d3d.depth_test = depth_test; - d3d.must_reload_pipeline = true; -} - -static void gfx_direct3d12_set_depth_mask(bool z_upd) { - d3d.depth_mask = z_upd; - d3d.must_reload_pipeline = true; -} - -static void gfx_direct3d12_set_zmode_decal(bool zmode_decal) { - d3d.zmode_decal = zmode_decal; - d3d.must_reload_pipeline = true; -} - -static void gfx_direct3d12_set_viewport(int x, int y, int width, int height) { - d3d.viewport = CD3DX12_VIEWPORT(x, d3d.current_height - y - height, width, height); -} - -static void gfx_direct3d12_set_scissor(int x, int y, int width, int height) { - d3d.scissor = CD3DX12_RECT(x, d3d.current_height - y - height, x + width, d3d.current_height - y); -} - -static void gfx_direct3d12_set_use_alpha(bool use_alpha) { - // Already part of the pipeline state from shader info -} - -static void gfx_direct3d12_draw_triangles(float buf_vbo[], size_t buf_vbo_len, size_t buf_vbo_num_tris) { - struct ShaderProgramD3D12 *prg = d3d.shader_program; - - if (d3d.must_reload_pipeline) { - ComPtr& pipeline_state = d3d.pipeline_states[PipelineDesc{ - prg->shader_id, - d3d.depth_test, - d3d.depth_mask, - d3d.zmode_decal, - 0 - }]; - if (pipeline_state.Get() == nullptr) { - D3D12_INPUT_ELEMENT_DESC ied[7] = { - {"POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 } - }; - uint32_t ied_pos = 1; - if (prg->used_textures[0] || prg->used_textures[1]) { - ied[ied_pos++] = D3D12_INPUT_ELEMENT_DESC{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}; - } - if (prg->shader_id & SHADER_OPT_FOG) { - ied[ied_pos++] = D3D12_INPUT_ELEMENT_DESC{"FOG", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}; - } - for (int i = 0; i < prg->num_inputs; i++) { - DXGI_FORMAT format = (prg->shader_id & SHADER_OPT_ALPHA) ? DXGI_FORMAT_R32G32B32A32_FLOAT : DXGI_FORMAT_R32G32B32_FLOAT; - ied[ied_pos++] = D3D12_INPUT_ELEMENT_DESC{"INPUT", (UINT)i, format, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}; - } - - D3D12_GRAPHICS_PIPELINE_STATE_DESC desc = {}; - desc.InputLayout = { ied, ied_pos }; - desc.pRootSignature = prg->root_signature.Get(); - desc.VS = CD3DX12_SHADER_BYTECODE(prg->vertex_shader.Get()); - desc.PS = CD3DX12_SHADER_BYTECODE(prg->pixel_shader.Get()); - desc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); - if (d3d.zmode_decal) { - desc.RasterizerState.SlopeScaledDepthBias = -2.0f; - } - desc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE; - if (prg->shader_id & SHADER_OPT_ALPHA) { - D3D12_BLEND_DESC bd = {}; - bd.AlphaToCoverageEnable = FALSE; - bd.IndependentBlendEnable = FALSE; - static const D3D12_RENDER_TARGET_BLEND_DESC default_rtbd = { - TRUE, FALSE, - D3D12_BLEND_SRC_ALPHA, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD, - D3D12_BLEND_ONE, D3D12_BLEND_INV_SRC_ALPHA, D3D12_BLEND_OP_ADD, - D3D12_LOGIC_OP_NOOP, - D3D12_COLOR_WRITE_ENABLE_ALL - }; - for (UINT i = 0; i < D3D12_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) { - bd.RenderTarget[i] = default_rtbd; - } - desc.BlendState = bd; - } else { - desc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); - } - desc.DepthStencilState.DepthEnable = d3d.depth_test; - desc.DepthStencilState.DepthWriteMask = d3d.depth_mask ? D3D12_DEPTH_WRITE_MASK_ALL : D3D12_DEPTH_WRITE_MASK_ZERO; - desc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL; - desc.DSVFormat = d3d.depth_test ? DXGI_FORMAT_D32_FLOAT : DXGI_FORMAT_UNKNOWN; - desc.SampleMask = UINT_MAX; - desc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; - desc.NumRenderTargets = 1; - desc.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM; - desc.SampleDesc.Count = 1; - ThrowIfFailed(d3d.device->CreateGraphicsPipelineState(&desc, IID_PPV_ARGS(&pipeline_state))); - } - d3d.pipeline_state = pipeline_state.Get(); - d3d.must_reload_pipeline = false; - } - - d3d.command_list->SetGraphicsRootSignature(prg->root_signature.Get()); - d3d.command_list->SetPipelineState(d3d.pipeline_state); - - ID3D12DescriptorHeap *heaps[] = { d3d.srv_heap.Get(), d3d.sampler_heap.Get() }; - d3d.command_list->SetDescriptorHeaps(2, heaps); - - int root_param_index = 0; - - if ((prg->shader_id & (SHADER_OPT_ALPHA | SHADER_OPT_NOISE)) == (SHADER_OPT_ALPHA | SHADER_OPT_NOISE)) { - d3d.command_list->SetGraphicsRootConstantBufferView(root_param_index++, d3d.noise_cb->GetGPUVirtualAddress()); - } - - for (int i = 0; i < 2; i++) { - if (prg->used_textures[i]) { - struct TextureData& td = d3d.textures[d3d.current_texture_ids[i]]; - if (td.last_frame_counter != d3d.frame_counter) { - td.descriptor_index = d3d.srv_pos; - td.last_frame_counter = d3d.frame_counter; - - D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc = {}; - srv_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - srv_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - srv_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; - srv_desc.Texture2D.MipLevels = 1; - - CD3DX12_CPU_DESCRIPTOR_HANDLE srv_handle(get_cpu_descriptor_handle(d3d.srv_heap), d3d.srv_pos++, d3d.srv_descriptor_size); - d3d.device->CreateShaderResourceView(td.resource.Get(), &srv_desc, srv_handle); - } - - CD3DX12_GPU_DESCRIPTOR_HANDLE srv_gpu_handle(get_gpu_descriptor_handle(d3d.srv_heap), td.descriptor_index, d3d.srv_descriptor_size); - d3d.command_list->SetGraphicsRootDescriptorTable(root_param_index++, srv_gpu_handle); - - CD3DX12_GPU_DESCRIPTOR_HANDLE sampler_gpu_handle(get_gpu_descriptor_handle(d3d.sampler_heap), td.sampler_parameters, d3d.sampler_descriptor_size); - d3d.command_list->SetGraphicsRootDescriptorTable(root_param_index++, sampler_gpu_handle); - } - } - - CD3DX12_CPU_DESCRIPTOR_HANDLE rtv_handle(get_cpu_descriptor_handle(d3d.rtv_heap), d3d.frame_index, d3d.rtv_descriptor_size); - D3D12_CPU_DESCRIPTOR_HANDLE dsv_handle = get_cpu_descriptor_handle(d3d.dsv_heap); - d3d.command_list->OMSetRenderTargets(1, &rtv_handle, FALSE, &dsv_handle); - - d3d.command_list->RSSetViewports(1, &d3d.viewport); - d3d.command_list->RSSetScissorRects(1, &d3d.scissor); - - int current_pos = d3d.vbuf_pos; - memcpy((uint8_t *)d3d.mapped_vbuf_address + current_pos, buf_vbo, buf_vbo_len * sizeof(float)); - d3d.vbuf_pos += buf_vbo_len * sizeof(float); - static int maxpos; - if (d3d.vbuf_pos > maxpos) { - maxpos = d3d.vbuf_pos; - //printf("NEW MAXPOS: %d\n", maxpos); - } - - D3D12_VERTEX_BUFFER_VIEW vertex_buffer_view; - vertex_buffer_view.BufferLocation = d3d.vertex_buffer->GetGPUVirtualAddress() + current_pos; - vertex_buffer_view.StrideInBytes = buf_vbo_len / (3 * buf_vbo_num_tris) * sizeof(float); - vertex_buffer_view.SizeInBytes = buf_vbo_len * sizeof(float); - - d3d.command_list->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - d3d.command_list->IASetVertexBuffers(0, 1, &vertex_buffer_view); - d3d.command_list->DrawInstanced(3 * buf_vbo_num_tris, 1, 0, 0); -} - -static void gfx_direct3d12_start_frame(void) { - - MoonInternal::bindHook(GFX_PRE_START_FRAME); - MoonInternal::initBindHook(0); - if(MoonInternal::callBindHook(1, (struct HookParameter){.name = "d3d", .parameter = (void*) &d3d})) return; - - ++d3d.frame_counter; - d3d.srv_pos = 0; - texture_uploads = 0; - ThrowIfFailed(d3d.command_allocator->Reset()); - ThrowIfFailed(d3d.command_list->Reset(d3d.command_allocator.Get(), nullptr)); - - CD3DX12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( - d3d.render_targets[d3d.frame_index].Get(), - D3D12_RESOURCE_STATE_PRESENT, - D3D12_RESOURCE_STATE_RENDER_TARGET); - d3d.command_list->ResourceBarrier(1, &barrier); - - CD3DX12_CPU_DESCRIPTOR_HANDLE rtv_handle(get_cpu_descriptor_handle(d3d.rtv_heap), d3d.frame_index, d3d.rtv_descriptor_size); - D3D12_CPU_DESCRIPTOR_HANDLE dsv_handle = get_cpu_descriptor_handle(d3d.dsv_heap); - d3d.command_list->OMSetRenderTargets(1, &rtv_handle, FALSE, &dsv_handle); - - static unsigned char c; - const float clear_color[] = { 0.0f, 0.0f, 0.0f, 1.0f }; - d3d.command_list->ClearRenderTargetView(rtv_handle, clear_color, 0, nullptr); - d3d.command_list->ClearDepthStencilView(dsv_handle, D3D12_CLEAR_FLAG_DEPTH, 1.0f, 0, 0, nullptr); - - d3d.noise_cb_data.noise_frame++; - if (d3d.noise_cb_data.noise_frame > 150) { - // No high values, as noise starts to look ugly - d3d.noise_cb_data.noise_frame = 0; - } - float aspect_ratio = (float) d3d.current_width / (float) d3d.current_height; - d3d.noise_cb_data.noise_scale_x = 120 * aspect_ratio; // 120 = N64 height resolution (240) / 2 - d3d.noise_cb_data.noise_scale_y = 120; - memcpy(d3d.mapped_noise_cb_address, &d3d.noise_cb_data, sizeof(struct NoiseCB)); - - d3d.vbuf_pos = 0; - - MoonInternal::bindHook(GFX_POST_START_FRAME); - MoonInternal::initBindHook(0); - MoonInternal::callBindHook(1, (struct HookParameter){.name = "d3d", .parameter = (void*) &d3d}); -} - -static void create_render_target_views(void) { - D3D12_CPU_DESCRIPTOR_HANDLE rtv_handle = get_cpu_descriptor_handle(d3d.rtv_heap); - for (UINT i = 0; i < 2; i++) { - ThrowIfFailed(d3d.swap_chain->GetBuffer(i, IID_ID3D12Resource, (void **)&d3d.render_targets[i])); - d3d.device->CreateRenderTargetView(d3d.render_targets[i].Get(), nullptr, rtv_handle); - rtv_handle.ptr += d3d.rtv_descriptor_size; - } -} - -static void create_depth_buffer(void) { - DXGI_SWAP_CHAIN_DESC1 desc1; - ThrowIfFailed(d3d.swap_chain->GetDesc1(&desc1)); - UINT width = desc1.Width; - UINT height = desc1.Height; - - d3d.current_width = width; - d3d.current_height = height; - - D3D12_DEPTH_STENCIL_VIEW_DESC dsv_desc = {}; - dsv_desc.Format = DXGI_FORMAT_D32_FLOAT; - dsv_desc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D; - dsv_desc.Flags = D3D12_DSV_FLAG_NONE; - - D3D12_CLEAR_VALUE depth_optimized_cv = {}; - depth_optimized_cv.Format = DXGI_FORMAT_D32_FLOAT; - depth_optimized_cv.DepthStencil.Depth = 1.0f; - - D3D12_HEAP_PROPERTIES hp = {}; - hp.Type = D3D12_HEAP_TYPE_DEFAULT; - hp.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN; - hp.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN; - hp.CreationNodeMask = 1; - hp.VisibleNodeMask = 1; - - D3D12_RESOURCE_DESC rd = {}; - rd.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; - rd.Alignment = 0; - rd.Width = width; - rd.Height = height; - rd.DepthOrArraySize = 1; - rd.MipLevels = 0; - rd.Format = DXGI_FORMAT_D32_FLOAT; - rd.SampleDesc.Count = 1; - rd.SampleDesc.Quality = 0; - rd.Flags = D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; - rd.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; - ThrowIfFailed(d3d.device->CreateCommittedResource(&hp, D3D12_HEAP_FLAG_NONE, &rd, D3D12_RESOURCE_STATE_DEPTH_WRITE, &depth_optimized_cv, IID_PPV_ARGS(&d3d.depth_stencil_buffer))); - - d3d.device->CreateDepthStencilView(d3d.depth_stencil_buffer.Get(), &dsv_desc, get_cpu_descriptor_handle(d3d.dsv_heap)); -} - -static void gfx_direct3d12_on_resize(void) { - if (d3d.render_targets[0].Get() != nullptr) { - d3d.render_targets[0].Reset(); - d3d.render_targets[1].Reset(); - ThrowIfFailed(d3d.swap_chain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT)); - d3d.frame_index = d3d.swap_chain->GetCurrentBackBufferIndex(); - create_render_target_views(); - create_depth_buffer(); - MoonInternal::bindHook(GFX_ON_REZISE); - MoonInternal::initBindHook(0); - MoonInternal::callBindHook(1, (struct HookParameter){.name = "d3d", .parameter = (void*) &d3d}); - } -} - -static void gfx_direct3d12_init(void ) { - // Load d3d12.dll - d3d.d3d12_module = LoadLibraryW(L"d3d12.dll"); - if (d3d.d3d12_module == nullptr) { - ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError()), gfx_dxgi_get_h_wnd(), "d3d12.dll could not be loaded"); - } - d3d.D3D12CreateDevice = (PFN_D3D12_CREATE_DEVICE)GetProcAddress(d3d.d3d12_module, "D3D12CreateDevice"); -#if DEBUG_D3D - d3d.D3D12GetDebugInterface = (PFN_D3D12_GET_DEBUG_INTERFACE)GetProcAddress(d3d.d3d12_module, "D3D12GetDebugInterface"); -#endif - - // Load D3DCompiler_47.dll - d3d.d3dcompiler_module = LoadLibraryW(L"D3DCompiler_47.dll"); - if (d3d.d3dcompiler_module == nullptr) { - ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError()), gfx_dxgi_get_h_wnd(), "D3DCompiler_47.dll could not be loaded"); - } - d3d.D3DCompile = (pD3DCompile)GetProcAddress(d3d.d3dcompiler_module, "D3DCompile"); - - // Create device - { - UINT debug_flags = 0; -#if DEBUG_D3D - ComPtr debug_controller; - if (SUCCEEDED(d3d.D3D12GetDebugInterface(IID_PPV_ARGS(&debug_controller)))) { - debug_controller->EnableDebugLayer(); - debug_flags |= DXGI_CREATE_FACTORY_DEBUG; - } -#endif - - gfx_dxgi_create_factory_and_device(DEBUG_D3D, 12, [](IDXGIAdapter1 *adapter, bool test_only) { - HRESULT res = d3d.D3D12CreateDevice( - adapter, - D3D_FEATURE_LEVEL_11_0, - IID_ID3D12Device, - test_only ? nullptr : IID_PPV_ARGS_Helper(&d3d.device)); - - if (test_only) { - return SUCCEEDED(res); - } else { - ThrowIfFailed(res, gfx_dxgi_get_h_wnd(), "Failed to create D3D12 device."); - return true; - } - }); - } - - // Create command queues - { - D3D12_COMMAND_QUEUE_DESC queue_desc = {}; - queue_desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; - queue_desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; - ThrowIfFailed(d3d.device->CreateCommandQueue(&queue_desc, IID_PPV_ARGS(&d3d.command_queue))); - } - { - D3D12_COMMAND_QUEUE_DESC queue_desc = {}; - queue_desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; - queue_desc.Type = D3D12_COMMAND_LIST_TYPE_COPY; - ThrowIfFailed(d3d.device->CreateCommandQueue(&queue_desc, IID_PPV_ARGS(&d3d.copy_command_queue))); - } - - // Create swap chain - { - ComPtr swap_chain1 = gfx_dxgi_create_swap_chain(d3d.command_queue.Get()); - ThrowIfFailed(swap_chain1->QueryInterface(__uuidof(IDXGISwapChain3), &d3d.swap_chain)); - d3d.frame_index = d3d.swap_chain->GetCurrentBackBufferIndex(); - } - - // Create render target views - { - D3D12_DESCRIPTOR_HEAP_DESC rtv_heap_desc = {}; - rtv_heap_desc.NumDescriptors = 2; - rtv_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; - rtv_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; - ThrowIfFailed(d3d.device->CreateDescriptorHeap(&rtv_heap_desc, IID_PPV_ARGS(&d3d.rtv_heap))); - d3d.rtv_descriptor_size = d3d.device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); - - create_render_target_views(); - } - - // Create Z-buffer - { - D3D12_DESCRIPTOR_HEAP_DESC dsv_heap_desc = {}; - dsv_heap_desc.NumDescriptors = 1; - dsv_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV; - dsv_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; - ThrowIfFailed(d3d.device->CreateDescriptorHeap(&dsv_heap_desc, IID_PPV_ARGS(&d3d.dsv_heap))); - - create_depth_buffer(); - } - - // Create SRV heap for texture descriptors - { - D3D12_DESCRIPTOR_HEAP_DESC srv_heap_desc = {}; - srv_heap_desc.NumDescriptors = 1024; // Max unique textures per frame - srv_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; - srv_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; - ThrowIfFailed(d3d.device->CreateDescriptorHeap(&srv_heap_desc, IID_PPV_ARGS(&d3d.srv_heap))); - d3d.srv_descriptor_size = d3d.device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - } - - // Create sampler heap and descriptors - { - D3D12_DESCRIPTOR_HEAP_DESC sampler_heap_desc = {}; - sampler_heap_desc.NumDescriptors = 18; - sampler_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER; - sampler_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; - ThrowIfFailed(d3d.device->CreateDescriptorHeap(&sampler_heap_desc, IID_PPV_ARGS(&d3d.sampler_heap))); - d3d.sampler_descriptor_size = d3d.device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); - - static const D3D12_TEXTURE_ADDRESS_MODE address_modes[] = { - D3D12_TEXTURE_ADDRESS_MODE_WRAP, - D3D12_TEXTURE_ADDRESS_MODE_MIRROR, - D3D12_TEXTURE_ADDRESS_MODE_CLAMP - }; - - D3D12_CPU_DESCRIPTOR_HANDLE sampler_handle = get_cpu_descriptor_handle(d3d.sampler_heap); - int pos = 0; - for (int linear_filter = 0; linear_filter < 2; linear_filter++) { - for (int cms = 0; cms < 3; cms++) { - for (int cmt = 0; cmt < 3; cmt++) { - D3D12_SAMPLER_DESC sampler_desc = {}; - sampler_desc.Filter = linear_filter ? D3D12_FILTER_MIN_MAG_MIP_LINEAR : D3D12_FILTER_MIN_MAG_MIP_POINT; - sampler_desc.AddressU = address_modes[cms]; - sampler_desc.AddressV = address_modes[cmt]; - sampler_desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP; - sampler_desc.MinLOD = 0; - sampler_desc.MaxLOD = D3D12_FLOAT32_MAX; - sampler_desc.MipLODBias = 0.0f; - sampler_desc.MaxAnisotropy = 1; - sampler_desc.ComparisonFunc = D3D12_COMPARISON_FUNC_NEVER; - d3d.device->CreateSampler(&sampler_desc, CD3DX12_CPU_DESCRIPTOR_HANDLE(sampler_handle, pos++, d3d.sampler_descriptor_size)); - } - } - } - } - - // Create constant buffer view for noise - { - /*D3D12_DESCRIPTOR_HEAP_DESC cbv_heap_desc = {}; - cbv_heap_desc.NumDescriptors = 1; - cbv_heap_desc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; - srv_heap_desc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; - ThrowIfFailed(d3d.device->CreateDescriptorHeap*/ - - CD3DX12_HEAP_PROPERTIES hp(D3D12_HEAP_TYPE_UPLOAD); - CD3DX12_RESOURCE_DESC rdb = CD3DX12_RESOURCE_DESC::Buffer(256); - ThrowIfFailed(d3d.device->CreateCommittedResource( - &hp, - D3D12_HEAP_FLAG_NONE, - &rdb, - D3D12_RESOURCE_STATE_GENERIC_READ, - nullptr, - IID_PPV_ARGS(&d3d.noise_cb))); - - CD3DX12_RANGE read_range(0, 0); // Read not possible from CPU - ThrowIfFailed(d3d.noise_cb->Map(0, &read_range, &d3d.mapped_noise_cb_address)); - } - - ThrowIfFailed(d3d.device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, IID_PPV_ARGS(&d3d.command_allocator))); - ThrowIfFailed(d3d.device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_COPY, IID_PPV_ARGS(&d3d.copy_command_allocator))); - - ThrowIfFailed(d3d.device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, d3d.command_allocator.Get(), nullptr, IID_PPV_ARGS(&d3d.command_list))); - ThrowIfFailed(d3d.device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_COPY, d3d.copy_command_allocator.Get(), nullptr, IID_PPV_ARGS(&d3d.copy_command_list))); - - ThrowIfFailed(d3d.command_list->Close()); - - ThrowIfFailed(d3d.device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&d3d.fence))); - d3d.fence_event = CreateEvent(nullptr, FALSE, FALSE, nullptr); - if (d3d.fence_event == nullptr) { - ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError())); - } - - ThrowIfFailed(d3d.device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&d3d.copy_fence))); - - { - // Create a buffer of 1 MB in size. With a 120 star speed run 192 kB seems to be max usage. - CD3DX12_HEAP_PROPERTIES hp(D3D12_HEAP_TYPE_UPLOAD); - CD3DX12_RESOURCE_DESC rdb = CD3DX12_RESOURCE_DESC::Buffer(256 * 1024 * sizeof(float)); - ThrowIfFailed(d3d.device->CreateCommittedResource( - &hp, - D3D12_HEAP_FLAG_NONE, - &rdb, - D3D12_RESOURCE_STATE_GENERIC_READ, - nullptr, - IID_PPV_ARGS(&d3d.vertex_buffer))); - - CD3DX12_RANGE read_range(0, 0); // Read not possible from CPU - ThrowIfFailed(d3d.vertex_buffer->Map(0, &read_range, &d3d.mapped_vbuf_address)); - } - - MoonInternal::bindHook(GFX_INIT); - MoonInternal::initBindHook(0); - MoonInternal::callBindHook(1, (struct HookParameter){.name = "d3d", .parameter = (void*) &d3d}); -} - -static void gfx_direct3d12_end_frame(void) { - MoonInternal::bindHook(GFX_PRE_END_FRAME); - MoonInternal::initBindHook(0); - if(MoonInternal::callBindHook(1, (struct HookParameter){.name = "d3d", .parameter = (void*) &d3d})) return; - - if (max_texture_uploads < texture_uploads && texture_uploads != 38 && texture_uploads != 34 && texture_uploads != 29) { - max_texture_uploads = texture_uploads; - } - //printf("Texture uploads: %d %d\n", max_texture_uploads, texture_uploads); - texture_uploads = 0; - - ThrowIfFailed(d3d.copy_command_list->Close()); - { - ID3D12CommandList *lists[] = { d3d.copy_command_list.Get() }; - d3d.copy_command_queue->ExecuteCommandLists(1, lists); - d3d.copy_command_queue->Signal(d3d.copy_fence.Get(), ++d3d.copy_fence_value); - } - - CD3DX12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( - d3d.render_targets[d3d.frame_index].Get(), - D3D12_RESOURCE_STATE_RENDER_TARGET, - D3D12_RESOURCE_STATE_PRESENT); - d3d.command_list->ResourceBarrier(1, &barrier); - - d3d.command_queue->Wait(d3d.copy_fence.Get(), d3d.copy_fence_value); - - ThrowIfFailed(d3d.command_list->Close()); - - { - ID3D12CommandList *lists[] = { d3d.command_list.Get() }; - d3d.command_queue->ExecuteCommandLists(1, lists); - } - - { - LARGE_INTEGER t0; - QueryPerformanceCounter(&t0); - //printf("Present: %llu %u\n", (unsigned long long)(t0.QuadPart - d3d.qpc_init), d3d.length_in_vsync_frames); - } - MoonInternal::bindHook(GFX_POST_END_FRAME); - MoonInternal::initBindHook(0); - MoonInternal::callBindHook(1, (struct HookParameter){.name = "d3d", .parameter = (void*) &d3d}); -} - -static void gfx_direct3d12_finish_render(void) { - LARGE_INTEGER t0, t1, t2; - QueryPerformanceCounter(&t0); - - static UINT64 fence_value; - ThrowIfFailed(d3d.command_queue->Signal(d3d.fence.Get(), ++fence_value)); - if (d3d.fence->GetCompletedValue() < fence_value) { - ThrowIfFailed(d3d.fence->SetEventOnCompletion(fence_value, d3d.fence_event)); - WaitForSingleObject(d3d.fence_event, INFINITE); - } - QueryPerformanceCounter(&t1); - - d3d.resources_to_clean_at_end_of_frame.clear(); - for (std::pair>& heap : d3d.upload_heaps_in_flight) { - d3d.upload_heaps[heap.first].push_back(std::move(heap.second)); - } - d3d.upload_heaps_in_flight.clear(); - for (std::pair& item : d3d.texture_heap_allocations_to_reclaim_at_end_of_frame) { - item.first->free_list.push_back(item.second); - } - d3d.texture_heap_allocations_to_reclaim_at_end_of_frame.clear(); - - QueryPerformanceCounter(&t2); - - d3d.frame_index = d3d.swap_chain->GetCurrentBackBufferIndex(); - - ThrowIfFailed(d3d.copy_command_allocator->Reset()); - ThrowIfFailed(d3d.copy_command_list->Reset(d3d.copy_command_allocator.Get(), nullptr)); - - //printf("done %llu gpu:%d wait:%d freed:%llu frame:%u %u monitor:%u t:%llu\n", (unsigned long long)(t0.QuadPart - d3d.qpc_init), (int)(t1.QuadPart - t0.QuadPart), (int)(t2.QuadPart - t0.QuadPart), (unsigned long long)(t2.QuadPart - d3d.qpc_init), d3d.pending_frame_stats.rbegin()->first, stats.PresentCount, stats.SyncRefreshCount, (unsigned long long)(stats.SyncQPCTime.QuadPart - d3d.qpc_init)); -} - -} // namespace - -struct GfxRenderingAPI gfx_direct3d12_api = { - gfx_direct3d12_z_is_from_0_to_1, - gfx_direct3d12_unload_shader, - gfx_direct3d12_load_shader, - gfx_direct3d12_create_and_load_new_shader, - gfx_direct3d12_lookup_shader, - gfx_direct3d12_shader_get_info, - gfx_direct3d12_new_texture, - gfx_direct3d12_select_texture, - gfx_direct3d12_upload_texture, - gfx_direct3d12_set_sampler_parameters, - gfx_direct3d12_set_depth_test, - gfx_direct3d12_set_depth_mask, - gfx_direct3d12_set_zmode_decal, - gfx_direct3d12_set_viewport, - gfx_direct3d12_set_scissor, - gfx_direct3d12_set_use_alpha, - gfx_direct3d12_draw_triangles, - gfx_direct3d12_init, - gfx_direct3d12_on_resize, - gfx_direct3d12_start_frame, - gfx_direct3d12_end_frame, - gfx_direct3d12_finish_render -}; - -#endif diff --git a/src/pc/gfx/gfx_direct3d12.h b/src/pc/gfx/gfx_direct3d12.h deleted file mode 100644 index 559566ff..00000000 --- a/src/pc/gfx/gfx_direct3d12.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifdef RAPI_D3D12 - -#ifndef GFX_DIRECT3D12_H -#define GFX_DIRECT3D12_H - -#include "gfx_rendering_api.h" - -extern struct GfxRenderingAPI gfx_direct3d12_api; - -#endif - -#endif diff --git a/src/pc/gfx/gfx_direct3d12_guids.h b/src/pc/gfx/gfx_direct3d12_guids.h deleted file mode 100644 index e18a0181..00000000 --- a/src/pc/gfx/gfx_direct3d12_guids.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef GFX_DIRECT3D12_GUIDS_H -#define GFX_DIRECT3D12_GUIDS_H - -#ifdef __MINGW32__ - -// This file is only needed due to missing MinGW-specific headers for d3d12.h. -// It will define IID_* symbols having the "selectany" attribute (assuming -// d3d12.h was earlier included), as well as make __uuidof(...) work. - -#define DEF_GUID(type,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ - __CRT_UUID_DECL(type,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \ - const GUID IID_##type = __uuidof(type) - -DEF_GUID(ID3D12Object,0xc4fec28f,0x7966,0x4e95,0x9f,0x94,0xf4,0x31,0xcb,0x56,0xc3,0xb8); -DEF_GUID(ID3D12DeviceChild,0x905db94b,0xa00c,0x4140,0x9d,0xf5,0x2b,0x64,0xca,0x9e,0xa3,0x57); -DEF_GUID(ID3D12RootSignature,0xc54a6b66,0x72df,0x4ee8,0x8b,0xe5,0xa9,0x46,0xa1,0x42,0x92,0x14); -DEF_GUID(ID3D12RootSignatureDeserializer,0x34AB647B,0x3CC8,0x46AC,0x84,0x1B,0xC0,0x96,0x56,0x45,0xC0,0x46); -DEF_GUID(ID3D12VersionedRootSignatureDeserializer,0x7F91CE67,0x090C,0x4BB7,0xB7,0x8E,0xED,0x8F,0xF2,0xE3,0x1D,0xA0); -DEF_GUID(ID3D12Pageable,0x63ee58fb,0x1268,0x4835,0x86,0xda,0xf0,0x08,0xce,0x62,0xf0,0xd6); -DEF_GUID(ID3D12Heap,0x6b3b2502,0x6e51,0x45b3,0x90,0xee,0x98,0x84,0x26,0x5e,0x8d,0xf3); -DEF_GUID(ID3D12Resource,0x696442be,0xa72e,0x4059,0xbc,0x79,0x5b,0x5c,0x98,0x04,0x0f,0xad); -DEF_GUID(ID3D12CommandAllocator,0x6102dee4,0xaf59,0x4b09,0xb9,0x99,0xb4,0x4d,0x73,0xf0,0x9b,0x24); -DEF_GUID(ID3D12Fence,0x0a753dcf,0xc4d8,0x4b91,0xad,0xf6,0xbe,0x5a,0x60,0xd9,0x5a,0x76); -DEF_GUID(ID3D12Fence1,0x433685fe,0xe22b,0x4ca0,0xa8,0xdb,0xb5,0xb4,0xf4,0xdd,0x0e,0x4a); -DEF_GUID(ID3D12PipelineState,0x765a30f3,0xf624,0x4c6f,0xa8,0x28,0xac,0xe9,0x48,0x62,0x24,0x45); -DEF_GUID(ID3D12DescriptorHeap,0x8efb471d,0x616c,0x4f49,0x90,0xf7,0x12,0x7b,0xb7,0x63,0xfa,0x51); -DEF_GUID(ID3D12QueryHeap,0x0d9658ae,0xed45,0x469e,0xa6,0x1d,0x97,0x0e,0xc5,0x83,0xca,0xb4); -DEF_GUID(ID3D12CommandSignature,0xc36a797c,0xec80,0x4f0a,0x89,0x85,0xa7,0xb2,0x47,0x50,0x82,0xd1); -DEF_GUID(ID3D12CommandList,0x7116d91c,0xe7e4,0x47ce,0xb8,0xc6,0xec,0x81,0x68,0xf4,0x37,0xe5); -DEF_GUID(ID3D12GraphicsCommandList,0x5b160d0f,0xac1b,0x4185,0x8b,0xa8,0xb3,0xae,0x42,0xa5,0xa4,0x55); -DEF_GUID(ID3D12GraphicsCommandList1,0x553103fb,0x1fe7,0x4557,0xbb,0x38,0x94,0x6d,0x7d,0x0e,0x7c,0xa7); -DEF_GUID(ID3D12GraphicsCommandList2,0x38C3E585,0xFF17,0x412C,0x91,0x50,0x4F,0xC6,0xF9,0xD7,0x2A,0x28); -DEF_GUID(ID3D12CommandQueue,0x0ec870a6,0x5d7e,0x4c22,0x8c,0xfc,0x5b,0xaa,0xe0,0x76,0x16,0xed); -DEF_GUID(ID3D12Device,0x189819f1,0x1db6,0x4b57,0xbe,0x54,0x18,0x21,0x33,0x9b,0x85,0xf7); -DEF_GUID(ID3D12PipelineLibrary,0xc64226a8,0x9201,0x46af,0xb4,0xcc,0x53,0xfb,0x9f,0xf7,0x41,0x4f); -DEF_GUID(ID3D12PipelineLibrary1,0x80eabf42,0x2568,0x4e5e,0xbd,0x82,0xc3,0x7f,0x86,0x96,0x1d,0xc3); -DEF_GUID(ID3D12Device1,0x77acce80,0x638e,0x4e65,0x88,0x95,0xc1,0xf2,0x33,0x86,0x86,0x3e); -DEF_GUID(ID3D12Device2,0x30baa41e,0xb15b,0x475c,0xa0,0xbb,0x1a,0xf5,0xc5,0xb6,0x43,0x28); -DEF_GUID(ID3D12Device3,0x81dadc15,0x2bad,0x4392,0x93,0xc5,0x10,0x13,0x45,0xc4,0xaa,0x98); -DEF_GUID(ID3D12ProtectedSession,0xA1533D18,0x0AC1,0x4084,0x85,0xB9,0x89,0xA9,0x61,0x16,0x80,0x6B); -DEF_GUID(ID3D12ProtectedResourceSession,0x6CD696F4,0xF289,0x40CC,0x80,0x91,0x5A,0x6C,0x0A,0x09,0x9C,0x3D); -DEF_GUID(ID3D12Device4,0xe865df17,0xa9ee,0x46f9,0xa4,0x63,0x30,0x98,0x31,0x5a,0xa2,0xe5); -DEF_GUID(ID3D12LifetimeOwner,0xe667af9f,0xcd56,0x4f46,0x83,0xce,0x03,0x2e,0x59,0x5d,0x70,0xa8); -DEF_GUID(ID3D12SwapChainAssistant,0xf1df64b6,0x57fd,0x49cd,0x88,0x07,0xc0,0xeb,0x88,0xb4,0x5c,0x8f); -DEF_GUID(ID3D12LifetimeTracker,0x3fd03d36,0x4eb1,0x424a,0xa5,0x82,0x49,0x4e,0xcb,0x8b,0xa8,0x13); -DEF_GUID(ID3D12StateObject,0x47016943,0xfca8,0x4594,0x93,0xea,0xaf,0x25,0x8b,0x55,0x34,0x6d); -DEF_GUID(ID3D12StateObjectProperties,0xde5fa827,0x9bf9,0x4f26,0x89,0xff,0xd7,0xf5,0x6f,0xde,0x38,0x60); -DEF_GUID(ID3D12Device5,0x8b4f173b,0x2fea,0x4b80,0x8f,0x58,0x43,0x07,0x19,0x1a,0xb9,0x5d); -DEF_GUID(ID3D12DeviceRemovedExtendedDataSettings,0x82BC481C,0x6B9B,0x4030,0xAE,0xDB,0x7E,0xE3,0xD1,0xDF,0x1E,0x63); -DEF_GUID(ID3D12DeviceRemovedExtendedData,0x98931D33,0x5AE8,0x4791,0xAA,0x3C,0x1A,0x73,0xA2,0x93,0x4E,0x71); -DEF_GUID(ID3D12Device6,0xc70b221b,0x40e4,0x4a17,0x89,0xaf,0x02,0x5a,0x07,0x27,0xa6,0xdc); -DEF_GUID(ID3D12Resource1,0x9D5E227A,0x4430,0x4161,0x88,0xB3,0x3E,0xCA,0x6B,0xB1,0x6E,0x19); -DEF_GUID(ID3D12Heap1,0x572F7389,0x2168,0x49E3,0x96,0x93,0xD6,0xDF,0x58,0x71,0xBF,0x6D); -DEF_GUID(ID3D12GraphicsCommandList3,0x6FDA83A7,0xB84C,0x4E38,0x9A,0xC8,0xC7,0xBD,0x22,0x01,0x6B,0x3D); -DEF_GUID(ID3D12MetaCommand,0xDBB84C27,0x36CE,0x4FC9,0xB8,0x01,0xF0,0x48,0xC4,0x6A,0xC5,0x70); -DEF_GUID(ID3D12GraphicsCommandList4,0x8754318e,0xd3a9,0x4541,0x98,0xcf,0x64,0x5b,0x50,0xdc,0x48,0x74); -DEF_GUID(ID3D12Tools,0x7071e1f0,0xe84b,0x4b33,0x97,0x4f,0x12,0xfa,0x49,0xde,0x65,0xc5); -DEF_GUID(ID3D12GraphicsCommandList5,0x55050859,0x4024,0x474c,0x87,0xf5,0x64,0x72,0xea,0xee,0x44,0xea); - -#endif - -#endif diff --git a/src/pc/gfx/gfx_direct3d_common.cpp b/src/pc/gfx/gfx_direct3d_common.cpp deleted file mode 100644 index c4d6014e..00000000 --- a/src/pc/gfx/gfx_direct3d_common.cpp +++ /dev/null @@ -1,313 +0,0 @@ -#if defined(RAPI_D3D11) || defined(RAPI_D3D12) - -#include - -#include "gfx_direct3d_common.h" -#include "gfx_cc.h" - -void get_cc_features(uint32_t shader_id, CCFeatures *cc_features) { - for (int i = 0; i < 4; i++) { - cc_features->c[0][i] = (shader_id >> (i * 3)) & 7; - cc_features->c[1][i] = (shader_id >> (12 + i * 3)) & 7; - } - - cc_features->opt_alpha = (shader_id & SHADER_OPT_ALPHA) != 0; - cc_features->opt_fog = (shader_id & SHADER_OPT_FOG) != 0; - cc_features->opt_texture_edge = (shader_id & SHADER_OPT_TEXTURE_EDGE) != 0; - cc_features->opt_noise = (shader_id & SHADER_OPT_NOISE) != 0; - - cc_features->used_textures[0] = false; - cc_features->used_textures[1] = false; - cc_features->num_inputs = 0; - - for (int i = 0; i < 2; i++) { - for (int j = 0; j < 4; j++) { - if (cc_features->c[i][j] >= SHADER_INPUT_1 && cc_features->c[i][j] <= SHADER_INPUT_4) { - if (cc_features->c[i][j] > cc_features->num_inputs) { - cc_features->num_inputs = cc_features->c[i][j]; - } - } - if (cc_features->c[i][j] == SHADER_TEXEL0 || cc_features->c[i][j] == SHADER_TEXEL0A) { - cc_features->used_textures[0] = true; - } - if (cc_features->c[i][j] == SHADER_TEXEL1) { - cc_features->used_textures[1] = true; - } - } - } - - cc_features->do_single[0] = cc_features->c[0][2] == 0; - cc_features->do_single[1] = cc_features->c[1][2] == 0; - cc_features->do_multiply[0] = cc_features->c[0][1] == 0 && cc_features->c[0][3] == 0; - cc_features->do_multiply[1] = cc_features->c[1][1] == 0 && cc_features->c[1][3] == 0; - cc_features->do_mix[0] = cc_features->c[0][1] == cc_features->c[0][3]; - cc_features->do_mix[1] = cc_features->c[1][1] == cc_features->c[1][3]; - cc_features->color_alpha_same = (shader_id & 0xfff) == ((shader_id >> 12) & 0xfff); -} - -static void append_str(char *buf, size_t *len, const char *str) { - while (*str != '\0') buf[(*len)++] = *str++; -} - -static void append_line(char *buf, size_t *len, const char *str) { - while (*str != '\0') buf[(*len)++] = *str++; - buf[(*len)++] = '\r'; - buf[(*len)++] = '\n'; -} - -static const char *shader_item_to_str(uint32_t item, bool with_alpha, bool only_alpha, bool inputs_have_alpha, bool hint_single_element) { - if (!only_alpha) { - switch (item) { - default: - case SHADER_0: - return with_alpha ? "float4(0.0, 0.0, 0.0, 0.0)" : "float3(0.0, 0.0, 0.0)"; - case SHADER_INPUT_1: - return with_alpha || !inputs_have_alpha ? "input.input1" : "input.input1.rgb"; - case SHADER_INPUT_2: - return with_alpha || !inputs_have_alpha ? "input.input2" : "input.input2.rgb"; - case SHADER_INPUT_3: - return with_alpha || !inputs_have_alpha ? "input.input3" : "input.input3.rgb"; - case SHADER_INPUT_4: - return with_alpha || !inputs_have_alpha ? "input.input4" : "input.input4.rgb"; - case SHADER_TEXEL0: - return with_alpha ? "texVal0" : "texVal0.rgb"; - case SHADER_TEXEL0A: - return hint_single_element ? "texVal0.a" : (with_alpha ? "float4(texVal0.a, texVal0.a, texVal0.a, texVal0.a)" : "float3(texVal0.a, texVal0.a, texVal0.a)"); - case SHADER_TEXEL1: - return with_alpha ? "texVal1" : "texVal1.rgb"; - } - } else { - switch (item) { - default: - case SHADER_0: - return "0.0"; - case SHADER_INPUT_1: - return "input.input1.a"; - case SHADER_INPUT_2: - return "input.input2.a"; - case SHADER_INPUT_3: - return "input.input3.a"; - case SHADER_INPUT_4: - return "input.input4.a"; - case SHADER_TEXEL0: - return "texVal0.a"; - case SHADER_TEXEL0A: - return "texVal0.a"; - case SHADER_TEXEL1: - return "texVal1.a"; - } - } -} - -static void append_formula(char *buf, size_t *len, const uint8_t c[2][4], bool do_single, bool do_multiply, bool do_mix, bool with_alpha, bool only_alpha, bool opt_alpha) { - if (do_single) { - append_str(buf, len, shader_item_to_str(c[only_alpha][3], with_alpha, only_alpha, opt_alpha, false)); - } else if (do_multiply) { - append_str(buf, len, shader_item_to_str(c[only_alpha][0], with_alpha, only_alpha, opt_alpha, false)); - append_str(buf, len, " * "); - append_str(buf, len, shader_item_to_str(c[only_alpha][2], with_alpha, only_alpha, opt_alpha, true)); - } else if (do_mix) { - append_str(buf, len, "lerp("); - append_str(buf, len, shader_item_to_str(c[only_alpha][1], with_alpha, only_alpha, opt_alpha, false)); - append_str(buf, len, ", "); - append_str(buf, len, shader_item_to_str(c[only_alpha][0], with_alpha, only_alpha, opt_alpha, false)); - append_str(buf, len, ", "); - append_str(buf, len, shader_item_to_str(c[only_alpha][2], with_alpha, only_alpha, opt_alpha, true)); - append_str(buf, len, ")"); - } else { - append_str(buf, len, "("); - append_str(buf, len, shader_item_to_str(c[only_alpha][0], with_alpha, only_alpha, opt_alpha, false)); - append_str(buf, len, " - "); - append_str(buf, len, shader_item_to_str(c[only_alpha][1], with_alpha, only_alpha, opt_alpha, false)); - append_str(buf, len, ") * "); - append_str(buf, len, shader_item_to_str(c[only_alpha][2], with_alpha, only_alpha, opt_alpha, true)); - append_str(buf, len, " + "); - append_str(buf, len, shader_item_to_str(c[only_alpha][3], with_alpha, only_alpha, opt_alpha, false)); - } -} - -void gfx_direct3d_common_build_shader(char buf[4096], size_t& len, size_t& num_floats, const CCFeatures& cc_features, bool include_root_signature, bool three_point_filtering) { - len = 0; - num_floats = 4; - - // Pixel shader input struct - - if (include_root_signature) { - append_str(buf, &len, "#define RS \"RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | DENY_VERTEX_SHADER_ROOT_ACCESS)"); - if (cc_features.opt_alpha && cc_features.opt_noise) { - append_str(buf, &len, ",CBV(b0, visibility = SHADER_VISIBILITY_PIXEL)"); - } - if (cc_features.used_textures[0]) { - append_str(buf, &len, ",DescriptorTable(SRV(t0), visibility = SHADER_VISIBILITY_PIXEL)"); - append_str(buf, &len, ",DescriptorTable(Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL)"); - } - if (cc_features.used_textures[1]) { - append_str(buf, &len, ",DescriptorTable(SRV(t1), visibility = SHADER_VISIBILITY_PIXEL)"); - append_str(buf, &len, ",DescriptorTable(Sampler(s1), visibility = SHADER_VISIBILITY_PIXEL)"); - } - append_line(buf, &len, "\""); - } - - append_line(buf, &len, "struct PSInput {"); - append_line(buf, &len, " float4 position : SV_POSITION;"); - if (cc_features.used_textures[0] || cc_features.used_textures[1]) { - append_line(buf, &len, " float2 uv : TEXCOORD;"); - num_floats += 2; - } - if (cc_features.opt_alpha && cc_features.opt_noise) { - append_line(buf, &len, " float4 screenPos : TEXCOORD1;"); - } - if (cc_features.opt_fog) { - append_line(buf, &len, " float4 fog : FOG;"); - num_floats += 4; - } - for (int i = 0; i < cc_features.num_inputs; i++) { - len += sprintf(buf + len, " float%d input%d : INPUT%d;\r\n", cc_features.opt_alpha ? 4 : 3, i + 1, i); - num_floats += cc_features.opt_alpha ? 4 : 3; - } - append_line(buf, &len, "};"); - - // Textures and samplers - - if (cc_features.used_textures[0]) { - append_line(buf, &len, "Texture2D g_texture0 : register(t0);"); - append_line(buf, &len, "SamplerState g_sampler0 : register(s0);"); - } - if (cc_features.used_textures[1]) { - append_line(buf, &len, "Texture2D g_texture1 : register(t1);"); - append_line(buf, &len, "SamplerState g_sampler1 : register(s1);"); - } - - // Constant buffer and random function - - if (cc_features.opt_alpha && cc_features.opt_noise) { - append_line(buf, &len, "cbuffer PerFrameCB : register(b0) {"); - append_line(buf, &len, " uint noise_frame;"); - append_line(buf, &len, " float2 noise_scale;"); - append_line(buf, &len, "}"); - - append_line(buf, &len, "float random(in float3 value) {"); - append_line(buf, &len, " float random = dot(value, float3(12.9898, 78.233, 37.719));"); - append_line(buf, &len, " return frac(sin(random) * 143758.5453);"); - append_line(buf, &len, "}"); - } - - // 3 point texture filtering - // Original author: ArthurCarvalho - // Based on GLSL implementation by twinaphex, mupen64plus-libretro project. - - if (three_point_filtering && (cc_features.used_textures[0] || cc_features.used_textures[1])) { - append_line(buf, &len, "cbuffer PerDrawCB : register(b1) {"); - append_line(buf, &len, " struct {"); - append_line(buf, &len, " uint width;"); - append_line(buf, &len, " uint height;"); - append_line(buf, &len, " bool linear_filtering;"); - append_line(buf, &len, " } textures[2];"); - append_line(buf, &len, "}"); - append_line(buf, &len, "#define TEX_OFFSET(tex, tSampler, texCoord, off, texSize) tex.Sample(tSampler, texCoord - off / texSize)"); - append_line(buf, &len, "float4 tex2D3PointFilter(in Texture2D tex, in SamplerState tSampler, in float2 texCoord, in float2 texSize) {"); - append_line(buf, &len, " float2 offset = frac(texCoord * texSize - float2(0.5, 0.5));"); - append_line(buf, &len, " offset -= step(1.0, offset.x + offset.y);"); - append_line(buf, &len, " float4 c0 = TEX_OFFSET(tex, tSampler, texCoord, offset, texSize);"); - append_line(buf, &len, " float4 c1 = TEX_OFFSET(tex, tSampler, texCoord, float2(offset.x - sign(offset.x), offset.y), texSize);"); - append_line(buf, &len, " float4 c2 = TEX_OFFSET(tex, tSampler, texCoord, float2(offset.x, offset.y - sign(offset.y)), texSize);"); - append_line(buf, &len, " return c0 + abs(offset.x)*(c1-c0) + abs(offset.y)*(c2-c0);"); - append_line(buf, &len, "}"); - } - - // Vertex shader - - append_str(buf, &len, "PSInput VSMain(float4 position : POSITION"); - if (cc_features.used_textures[0] || cc_features.used_textures[1]) { - append_str(buf, &len, ", float2 uv : TEXCOORD"); - } - if (cc_features.opt_fog) { - append_str(buf, &len, ", float4 fog : FOG"); - } - for (int i = 0; i < cc_features.num_inputs; i++) { - len += sprintf(buf + len, ", float%d input%d : INPUT%d", cc_features.opt_alpha ? 4 : 3, i + 1, i); - } - append_line(buf, &len, ") {"); - append_line(buf, &len, " PSInput result;"); - append_line(buf, &len, " result.position = position;"); - if (cc_features.opt_alpha && cc_features.opt_noise) { - append_line(buf, &len, " result.screenPos = position;"); - } - if (cc_features.used_textures[0] || cc_features.used_textures[1]) { - append_line(buf, &len, " result.uv = uv;"); - } - if (cc_features.opt_fog) { - append_line(buf, &len, " result.fog = fog;"); - } - for (int i = 0; i < cc_features.num_inputs; i++) { - len += sprintf(buf + len, " result.input%d = input%d;\r\n", i + 1, i + 1); - } - append_line(buf, &len, " return result;"); - append_line(buf, &len, "}"); - - // Pixel shader - if (include_root_signature) { - append_line(buf, &len, "[RootSignature(RS)]"); - } - append_line(buf, &len, "float4 PSMain(PSInput input) : SV_TARGET {"); - if (cc_features.used_textures[0]) { - if (three_point_filtering) { - append_line(buf, &len, " float4 texVal0;"); - append_line(buf, &len, " if (textures[0].linear_filtering)"); - append_line(buf, &len, " texVal0 = tex2D3PointFilter(g_texture0, g_sampler0, input.uv, float2(textures[0].width, textures[0].height));"); - append_line(buf, &len, " else"); - append_line(buf, &len, " texVal0 = g_texture0.Sample(g_sampler0, input.uv);"); - } else { - append_line(buf, &len, " float4 texVal0 = g_texture0.Sample(g_sampler0, input.uv);"); - } - } - if (cc_features.used_textures[1]) { - if (three_point_filtering) { - append_line(buf, &len, " float4 texVal1;"); - append_line(buf, &len, " if (textures[1].linear_filtering)"); - append_line(buf, &len, " texVal1 = tex2D3PointFilter(g_texture1, g_sampler1, input.uv, float2(textures[1].width, textures[1].height));"); - append_line(buf, &len, " else"); - append_line(buf, &len, " texVal1 = g_texture1.Sample(g_sampler1, input.uv);"); - } else { - append_line(buf, &len, " float4 texVal1 = g_texture1.Sample(g_sampler1, input.uv);"); - } - } - - append_str(buf, &len, cc_features.opt_alpha ? " float4 texel = " : " float3 texel = "); - if (!cc_features.color_alpha_same && cc_features.opt_alpha) { - append_str(buf, &len, "float4("); - append_formula(buf, &len, cc_features.c, cc_features.do_single[0], cc_features.do_multiply[0], cc_features.do_mix[0], false, false, true); - append_str(buf, &len, ", "); - append_formula(buf, &len, cc_features.c, cc_features.do_single[1], cc_features.do_multiply[1], cc_features.do_mix[1], true, true, true); - append_str(buf, &len, ")"); - } else { - append_formula(buf, &len, cc_features.c, cc_features.do_single[0], cc_features.do_multiply[0], cc_features.do_mix[0], cc_features.opt_alpha, false, cc_features.opt_alpha); - } - append_line(buf, &len, ";"); - - if (cc_features.opt_texture_edge && cc_features.opt_alpha) { - append_line(buf, &len, " if (texel.a > 0.3) texel.a = 1.0; else discard;"); - } - // TODO discard if alpha is 0? - if (cc_features.opt_fog) { - if (cc_features.opt_alpha) { - append_line(buf, &len, " texel = float4(lerp(texel.rgb, input.fog.rgb, input.fog.a), texel.a);"); - } else { - append_line(buf, &len, " texel = lerp(texel, input.fog.rgb, input.fog.a);"); - } - } - - if (cc_features.opt_alpha && cc_features.opt_noise) { - append_line(buf, &len, " float2 coords = (input.screenPos.xy / input.screenPos.w) * noise_scale;"); - append_line(buf, &len, " texel.a *= round(random(float3(floor(coords), noise_frame)));"); - } - - if (cc_features.opt_alpha) { - append_line(buf, &len, " return texel;"); - } else { - append_line(buf, &len, " return float4(texel, 1.0);"); - } - append_line(buf, &len, "}"); -} - -#endif diff --git a/src/pc/gfx/gfx_direct3d_common.h b/src/pc/gfx/gfx_direct3d_common.h deleted file mode 100644 index 1eb316d7..00000000 --- a/src/pc/gfx/gfx_direct3d_common.h +++ /dev/null @@ -1,14 +0,0 @@ -#if defined(RAPI_D3D11) || defined(RAPI_D3D12) - -#ifndef GFX_DIRECT3D_COMMON_H -#define GFX_DIRECT3D_COMMON_H - -#include - -#include "gfx_cc.h" - -void gfx_direct3d_common_build_shader(char buf[4096], size_t& len, size_t& num_floats, const CCFeatures& cc_features, bool include_root_signature, bool three_point_filtering); - -#endif - -#endif diff --git a/src/pc/gfx/gfx_dxgi.cpp b/src/pc/gfx/gfx_dxgi.cpp deleted file mode 100644 index 04674952..00000000 --- a/src/pc/gfx/gfx_dxgi.cpp +++ /dev/null @@ -1,641 +0,0 @@ -#ifdef WAPI_DXGI - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include - - -#ifndef _LANGUAGE_C -#define _LANGUAGE_C -#endif -#include - -#include "../configfile.h" -#include "../pc_main.h" - -#include "gfx_window_manager_api.h" -#include "gfx_rendering_api.h" -#include "gfx_direct3d_common.h" -#include "gfx_screen_config.h" -#include "gfx_pc.h" - -#define WINCLASS_NAME L"N64GAME" - -#define DECLARE_GFX_DXGI_FUNCTIONS -#include "gfx_dxgi.h" - -#ifdef VERSION_EU -#define FRAME_INTERVAL_US_NUMERATOR 40000 -#define FRAME_INTERVAL_US_DENOMINATOR 1 -#else -#define FRAME_INTERVAL_US_NUMERATOR 100000 -#define FRAME_INTERVAL_US_DENOMINATOR 3 -#endif - -using namespace Microsoft::WRL; // For ComPtr - -static struct { - HWND h_wnd; - bool showing_error; - uint32_t current_width, current_height; - std::string window_title; - - HMODULE dxgi_module; - HRESULT (__stdcall *CreateDXGIFactory1)(REFIID riid, void **factory); - HRESULT (__stdcall *CreateDXGIFactory2)(UINT flags, REFIID iid, void **factory); - - bool process_dpi_awareness_done; - - RECT last_window_rect; - bool is_full_screen, last_maximized_state; - - ComPtr factory; - ComPtr swap_chain; - HANDLE waitable_object; - uint64_t qpc_init, qpc_freq; - uint64_t frame_timestamp; // in units of 1/FRAME_INTERVAL_US_DENOMINATOR microseconds - std::map frame_stats; - std::set> pending_frame_stats; - bool dropped_frame; - bool sync_interval_means_frames_to_wait; - UINT length_in_vsync_frames; - - void (*run_one_game_iter)(void); - bool (*on_key_down)(int scancode); - bool (*on_key_up)(int scancode); - void (*on_all_keys_up)(void); -} dxgi; - -static void load_dxgi_library(void) { - dxgi.dxgi_module = LoadLibraryW(L"dxgi.dll"); - *(FARPROC *)&dxgi.CreateDXGIFactory1 = GetProcAddress(dxgi.dxgi_module, "CreateDXGIFactory1"); - *(FARPROC *)&dxgi.CreateDXGIFactory2 = GetProcAddress(dxgi.dxgi_module, "CreateDXGIFactory2"); -} - -template -static void run_as_dpi_aware(Fun f) { - // Make sure Windows 8.1 or newer doesn't upscale/downscale the rendered images. - // This is an issue on Windows 8.1 and newer where moving around the window - // between different monitors having different scaling settings will - // by default result in the DirectX image will also be scaled accordingly. - // The resulting scale factor is the curent monitor's scale factor divided by - // the initial monitor's scale factor. Setting per-monitor aware disables scaling. - - // On Windows 10 1607 and later, that is solved by setting the awarenenss per window, - // which is done by using SetThreadDpiAwarenessContext before and after creating - // any window. When the message handler runs, the corresponding context also applies. - - // From windef.h, missing in MinGW. - DECLARE_HANDLE(DPI_AWARENESS_CONTEXT); - #define DPI_AWARENESS_CONTEXT_UNAWARE ((DPI_AWARENESS_CONTEXT)-1) - #define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE ((DPI_AWARENESS_CONTEXT)-2) - #define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ((DPI_AWARENESS_CONTEXT)-3) - #define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((DPI_AWARENESS_CONTEXT)-4) - #define DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED ((DPI_AWARENESS_CONTEXT)-5) - - DPI_AWARENESS_CONTEXT (WINAPI *SetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT dpiContext); - *(FARPROC *)&SetThreadDpiAwarenessContext = GetProcAddress(GetModuleHandleW(L"user32.dll"), "SetThreadDpiAwarenessContext"); - DPI_AWARENESS_CONTEXT old_awareness_context; - if (SetThreadDpiAwarenessContext != nullptr) { - old_awareness_context = SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); - } else { - // Solution for Windows 8.1 and newer, but before Windows 10 1607. - // SetProcessDpiAwareness must be called before any drawing related API is called. - if (!dxgi.process_dpi_awareness_done) { - HMODULE shcore_module = LoadLibraryW(L"SHCore.dll"); - if (shcore_module != nullptr) { - HRESULT (WINAPI *SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS value); - *(FARPROC *)&SetProcessDpiAwareness = GetProcAddress(shcore_module, "SetProcessDpiAwareness"); - if (SetProcessDpiAwareness != nullptr) { - SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE); - // Ignore result, will fail if already called or manifest already specifies dpi awareness. - } - FreeLibrary(shcore_module); - } - dxgi.process_dpi_awareness_done = true; - } - } - - f(); - - // Restore the old context - if (SetThreadDpiAwarenessContext != nullptr && old_awareness_context != nullptr) { - SetThreadDpiAwarenessContext(old_awareness_context); - } -} - -static void toggle_borderless_window_full_screen(bool enable) { - // Windows 7 + flip mode + waitable object can't go to exclusive fullscreen, - // so do borderless instead. If DWM is enabled, this means we get one monitor - // sync interval of latency extra. On Win 10 however (maybe Win 8 too), due to - // "fullscreen optimizations" the latency is eliminated. - - if (enable == dxgi.is_full_screen) { - return; - } - - if (!enable) { - RECT r = dxgi.last_window_rect; - - // Set in window mode with the last saved position and size - SetWindowLongPtr(dxgi.h_wnd, GWL_STYLE, WS_VISIBLE | WS_OVERLAPPEDWINDOW); - - if (dxgi.last_maximized_state) { - SetWindowPos(dxgi.h_wnd, NULL, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE); - ShowWindow(dxgi.h_wnd, SW_MAXIMIZE); - } else { - SetWindowPos(dxgi.h_wnd, NULL, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_FRAMECHANGED); - ShowWindow(dxgi.h_wnd, SW_RESTORE); - } - - ShowCursor(TRUE); - - dxgi.is_full_screen = false; - } else { - // Save if window is maximized or not - WINDOWPLACEMENT window_placement; - window_placement.length = sizeof(WINDOWPLACEMENT); - GetWindowPlacement(dxgi.h_wnd, &window_placement); - dxgi.last_maximized_state = window_placement.showCmd == SW_SHOWMAXIMIZED; - - // Save window position and size if the window is not maximized - GetWindowRect(dxgi.h_wnd, &dxgi.last_window_rect); - configWindow.x = dxgi.last_window_rect.left; - configWindow.y = dxgi.last_window_rect.top; - configWindow.w = dxgi.last_window_rect.right - dxgi.last_window_rect.left; - configWindow.h = dxgi.last_window_rect.bottom - dxgi.last_window_rect.top; - - // Get in which monitor the window is - HMONITOR h_monitor = MonitorFromWindow(dxgi.h_wnd, MONITOR_DEFAULTTONEAREST); - - // Get info from that monitor - MONITORINFOEX monitor_info; - monitor_info.cbSize = sizeof(MONITORINFOEX); - GetMonitorInfo(h_monitor, &monitor_info); - RECT r = monitor_info.rcMonitor; - - // Set borderless full screen to that monitor - SetWindowLongPtr(dxgi.h_wnd, GWL_STYLE, WS_VISIBLE | WS_POPUP); - SetWindowPos(dxgi.h_wnd, HWND_TOP, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_FRAMECHANGED); - - ShowCursor(FALSE); - - dxgi.is_full_screen = true; - } -} - -static void update_screen_settings(void) { - if (configWindow.fullscreen != dxgi.is_full_screen) - toggle_borderless_window_full_screen(configWindow.fullscreen); - if (!dxgi.is_full_screen) { - const int screen_width = GetSystemMetrics(SM_CXSCREEN); - const int screen_height = GetSystemMetrics(SM_CYSCREEN); - const int xpos = (configWindow.x == WAPI_WIN_CENTERPOS) ? (screen_width - configWindow.w) * 0.5 : configWindow.x; - const int ypos = (configWindow.y == WAPI_WIN_CENTERPOS) ? (screen_height - configWindow.h) * 0.5 : configWindow.y; - RECT wr = { xpos, ypos, xpos + (int)configWindow.w, ypos + (int)configWindow.h }; - AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); - SetWindowPos(dxgi.h_wnd, NULL, wr.left, wr.top, wr.right - wr.left, wr.bottom - wr.top, SWP_NOACTIVATE | SWP_NOZORDER); - } -} - -static void gfx_dxgi_on_resize(void) { - if (dxgi.swap_chain.Get() != nullptr) { - gfx_get_current_rendering_api()->on_resize(); - - DXGI_SWAP_CHAIN_DESC1 desc1; - ThrowIfFailed(dxgi.swap_chain->GetDesc1(&desc1)); - dxgi.current_width = desc1.Width; - dxgi.current_height = desc1.Height; - if (!dxgi.is_full_screen) { - configWindow.w = dxgi.current_width; - configWindow.h = dxgi.current_height; - } - } -} - -static void onkeydown(WPARAM w_param, LPARAM l_param) { - int key = ((l_param >> 16) & 0x1ff); - if (dxgi.on_key_down != nullptr) { - dxgi.on_key_down(key); - } -} -static void onkeyup(WPARAM w_param, LPARAM l_param) { - int key = ((l_param >> 16) & 0x1ff); - if (dxgi.on_key_up != nullptr) { - dxgi.on_key_up(key); - } -} - -static LRESULT CALLBACK gfx_dxgi_wnd_proc(HWND h_wnd, UINT message, WPARAM w_param, LPARAM l_param) { - switch (message) { - case WM_SIZE: - gfx_dxgi_on_resize(); - break; - case WM_DESTROY: - game_exit(); - break; - case WM_PAINT: - if (dxgi.showing_error) { - return DefWindowProcW(h_wnd, message, w_param, l_param); - } else { - if (dxgi.run_one_game_iter != nullptr) { - dxgi.run_one_game_iter(); - } - } - break; - case WM_ACTIVATEAPP: - if (dxgi.on_all_keys_up != nullptr) { - dxgi.on_all_keys_up(); - } - break; - case WM_KEYDOWN: - onkeydown(w_param, l_param); - break; - case WM_KEYUP: - onkeyup(w_param, l_param); - break; - case WM_SYSKEYDOWN: - if ((w_param == VK_RETURN) && ((l_param & 1 << 30) == 0)) { - toggle_borderless_window_full_screen(!dxgi.is_full_screen); - break; - } else { - return DefWindowProcW(h_wnd, message, w_param, l_param); - } - default: - return DefWindowProcW(h_wnd, message, w_param, l_param); - } - - if (configWindow.reset) { - dxgi.last_maximized_state = false; - configWindow.reset = false; - configWindow.x = WAPI_WIN_CENTERPOS; - configWindow.y = WAPI_WIN_CENTERPOS; - configWindow.w = DESIRED_SCREEN_WIDTH; - configWindow.h = DESIRED_SCREEN_HEIGHT; - configWindow.fullscreen = false; - configWindow.settings_changed = true; - } - - if (configWindow.settings_changed) { - configWindow.settings_changed = false; - update_screen_settings(); - } - - return 0; -} - -static void gfx_dxgi_init(const char *window_title) { - LARGE_INTEGER qpc_init, qpc_freq; - QueryPerformanceCounter(&qpc_init); - QueryPerformanceFrequency(&qpc_freq); - dxgi.qpc_init = qpc_init.QuadPart; - dxgi.qpc_freq = qpc_freq.QuadPart; - - // Prepare window title - - wchar_t w_title[512]; - int len = strlen(window_title); - mbstowcs(w_title, window_title, len + 1); - dxgi.window_title = window_title; - - // Create window - WNDCLASSEXW wcex; - - wcex.cbSize = sizeof(WNDCLASSEX); - - wcex.style = CS_HREDRAW | CS_VREDRAW; - wcex.lpfnWndProc = gfx_dxgi_wnd_proc; - wcex.cbClsExtra = 0; - wcex.cbWndExtra = 0; - wcex.hInstance = nullptr; - wcex.hIcon = nullptr; - wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); - wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); - wcex.lpszMenuName = nullptr; - wcex.lpszClassName = WINCLASS_NAME; - wcex.hIconSm = nullptr; - - ATOM winclass = RegisterClassExW(&wcex); - - - run_as_dpi_aware([&] () { - // We need to be dpi aware when calculating the size - RECT wr = {0, 0, DESIRED_SCREEN_WIDTH, DESIRED_SCREEN_HEIGHT}; - AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE); - - dxgi.h_wnd = CreateWindowW(WINCLASS_NAME, w_title, WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, 0, wr.right - wr.left, wr.bottom - wr.top, nullptr, nullptr, nullptr, nullptr); - }); - - load_dxgi_library(); - - ShowWindow(dxgi.h_wnd, SW_SHOW); - UpdateWindow(dxgi.h_wnd); - - update_screen_settings(); -} - -static void gfx_dxgi_set_keyboard_callbacks(bool (*on_key_down)(int scancode), bool (*on_key_up)(int scancode), void (*on_all_keys_up)(void)) { - dxgi.on_key_down = on_key_down; - dxgi.on_key_up = on_key_up; - dxgi.on_all_keys_up = on_all_keys_up; -} - -static void gfx_dxgi_main_loop(void (*run_one_game_iter)(void)) { - dxgi.run_one_game_iter = run_one_game_iter; - - MSG msg; - while (GetMessage(&msg, nullptr, 0, 0)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } -} - -static void gfx_dxgi_get_dimensions(uint32_t *width, uint32_t *height) { - *width = dxgi.current_width; - *height = dxgi.current_height; -} - -static void gfx_dxgi_handle_events(void) { - /*MSG msg; - while (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - }*/ -} - -static uint64_t qpc_to_us(uint64_t qpc) { - return qpc / dxgi.qpc_freq * 1000000 + qpc % dxgi.qpc_freq * 1000000 / dxgi.qpc_freq; -} - -static bool gfx_dxgi_start_frame(void) { - DXGI_FRAME_STATISTICS stats; - if (dxgi.swap_chain->GetFrameStatistics(&stats) == S_OK && (stats.SyncRefreshCount != 0 || stats.SyncQPCTime.QuadPart != 0ULL)) { - { - LARGE_INTEGER t0; - QueryPerformanceCounter(&t0); - //printf("Get frame stats: %llu\n", (unsigned long long)(t0.QuadPart - dxgi.qpc_init)); - } - //printf("stats: %u %u %u %u %u %.6f\n", dxgi.pending_frame_stats.rbegin()->first, dxgi.pending_frame_stats.rbegin()->second, stats.PresentCount, stats.PresentRefreshCount, stats.SyncRefreshCount, (double)(stats.SyncQPCTime.QuadPart - dxgi.qpc_init) / dxgi.qpc_freq); - if (dxgi.frame_stats.empty() || dxgi.frame_stats.rbegin()->second.PresentCount != stats.PresentCount) { - dxgi.frame_stats.insert(std::make_pair(stats.PresentCount, stats)); - } - if (dxgi.frame_stats.size() > 3) { - dxgi.frame_stats.erase(dxgi.frame_stats.begin()); - } - } - if (!dxgi.frame_stats.empty()) { - while (!dxgi.pending_frame_stats.empty() && dxgi.pending_frame_stats.begin()->first < dxgi.frame_stats.rbegin()->first) { - dxgi.pending_frame_stats.erase(dxgi.pending_frame_stats.begin()); - } - } - while (dxgi.pending_frame_stats.size() > 15) { - // Just make sure the list doesn't grow too large if GetFrameStatistics fails. - dxgi.pending_frame_stats.erase(dxgi.pending_frame_stats.begin()); - } - - dxgi.frame_timestamp += FRAME_INTERVAL_US_NUMERATOR; - - if (dxgi.frame_stats.size() >= 2) { - DXGI_FRAME_STATISTICS *first = &dxgi.frame_stats.begin()->second; - DXGI_FRAME_STATISTICS *last = &dxgi.frame_stats.rbegin()->second; - uint64_t sync_qpc_diff = last->SyncQPCTime.QuadPart - first->SyncQPCTime.QuadPart; - UINT sync_vsync_diff = last->SyncRefreshCount - first->SyncRefreshCount; - UINT present_vsync_diff = last->PresentRefreshCount - first->PresentRefreshCount; - UINT present_diff = last->PresentCount - first->PresentCount; - - if (sync_vsync_diff == 0) { - sync_vsync_diff = 1; - } - - double estimated_vsync_interval = (double)sync_qpc_diff / (double)sync_vsync_diff; - uint64_t estimated_vsync_interval_us = qpc_to_us(estimated_vsync_interval); - //printf("Estimated vsync_interval: %d\n", (int)estimated_vsync_interval_us); - if (estimated_vsync_interval_us < 2 || estimated_vsync_interval_us > 1000000) { - // Unreasonable, maybe a monitor change - estimated_vsync_interval_us = 16666; - estimated_vsync_interval = estimated_vsync_interval_us * dxgi.qpc_freq / 1000000; - } - - UINT queued_vsyncs = 0; - bool is_first = true; - for (const std::pair& p : dxgi.pending_frame_stats) { - if (is_first && dxgi.sync_interval_means_frames_to_wait) { - is_first = false; - continue; - } - queued_vsyncs += p.second; - } - - uint64_t last_frame_present_end_qpc = (last->SyncQPCTime.QuadPart - dxgi.qpc_init) + estimated_vsync_interval * queued_vsyncs; - uint64_t last_end_us = qpc_to_us(last_frame_present_end_qpc); - - double vsyncs_to_wait = (double)(int64_t)(dxgi.frame_timestamp / FRAME_INTERVAL_US_DENOMINATOR - last_end_us) / estimated_vsync_interval_us; - //printf("ts: %llu, last_end_us: %llu, Init v: %f\n", dxgi.frame_timestamp / 3, last_end_us, vsyncs_to_wait); - - if (vsyncs_to_wait <= 0) { - // Too late - - if ((int64_t)(dxgi.frame_timestamp / FRAME_INTERVAL_US_DENOMINATOR - last_end_us) < -66666) { - // The application must have been paused or similar - vsyncs_to_wait = round(((double)FRAME_INTERVAL_US_NUMERATOR / FRAME_INTERVAL_US_DENOMINATOR) / estimated_vsync_interval_us); - if (vsyncs_to_wait < 1) { - vsyncs_to_wait = 1; - } - dxgi.frame_timestamp = FRAME_INTERVAL_US_DENOMINATOR * (last_end_us + vsyncs_to_wait * estimated_vsync_interval_us); - } else { - // Drop frame - //printf("Dropping frame\n"); - dxgi.dropped_frame = true; - return false; - } - } - if (floor(vsyncs_to_wait) != vsyncs_to_wait) { - uint64_t left = last_end_us + floor(vsyncs_to_wait) * estimated_vsync_interval_us; - uint64_t right = last_end_us + ceil(vsyncs_to_wait) * estimated_vsync_interval_us; - uint64_t adjusted_desired_time = dxgi.frame_timestamp / FRAME_INTERVAL_US_DENOMINATOR + (last_end_us + (FRAME_INTERVAL_US_NUMERATOR / FRAME_INTERVAL_US_DENOMINATOR) > dxgi.frame_timestamp / FRAME_INTERVAL_US_DENOMINATOR ? 2000 : -2000); - int64_t diff_left = adjusted_desired_time - left; - int64_t diff_right = right - adjusted_desired_time; - if (diff_left < 0) { - diff_left = -diff_left; - } - if (diff_right < 0) { - diff_right = -diff_right; - } - if (diff_left < diff_right) { - vsyncs_to_wait = floor(vsyncs_to_wait); - } else { - vsyncs_to_wait = ceil(vsyncs_to_wait); - } - if (vsyncs_to_wait == 0) { - //printf("vsyncs_to_wait became 0 so dropping frame\n"); - dxgi.dropped_frame = true; - return false; - } - } - //printf("v: %d\n", (int)vsyncs_to_wait); - if (vsyncs_to_wait > 4) { - // Invalid, so change to 4 - vsyncs_to_wait = 4; - } - dxgi.length_in_vsync_frames = vsyncs_to_wait; - } else { - dxgi.length_in_vsync_frames = 2; - } - - return true; -} - -static void gfx_dxgi_swap_buffers_begin(void) { - //dxgi.length_in_vsync_frames = 1; - ThrowIfFailed(dxgi.swap_chain->Present(dxgi.length_in_vsync_frames, 0)); - UINT this_present_id; - if (dxgi.swap_chain->GetLastPresentCount(&this_present_id) == S_OK) { - dxgi.pending_frame_stats.insert(std::make_pair(this_present_id, dxgi.length_in_vsync_frames)); - } - dxgi.dropped_frame = false; -} - -static void gfx_dxgi_swap_buffers_end(void) { - LARGE_INTEGER t0, t1, t2; - QueryPerformanceCounter(&t0); - QueryPerformanceCounter(&t1); - - if (!dxgi.dropped_frame) { - if (dxgi.waitable_object != nullptr) { - WaitForSingleObject(dxgi.waitable_object, INFINITE); - } - // else TODO: maybe sleep until some estimated time the frame will be shown to reduce lag - } - - DXGI_FRAME_STATISTICS stats; - dxgi.swap_chain->GetFrameStatistics(&stats); - - QueryPerformanceCounter(&t2); - - dxgi.sync_interval_means_frames_to_wait = dxgi.pending_frame_stats.rbegin()->first == stats.PresentCount; - - //printf("done %llu gpu:%d wait:%d freed:%llu frame:%u %u monitor:%u t:%llu\n", (unsigned long long)(t0.QuadPart - dxgi.qpc_init), (int)(t1.QuadPart - t0.QuadPart), (int)(t2.QuadPart - t0.QuadPart), (unsigned long long)(t2.QuadPart - dxgi.qpc_init), dxgi.pending_frame_stats.rbegin()->first, stats.PresentCount, stats.SyncRefreshCount, (unsigned long long)(stats.SyncQPCTime.QuadPart - dxgi.qpc_init)); -} - -static double gfx_dxgi_get_time(void) { - LARGE_INTEGER t; - QueryPerformanceCounter(&t); - return (double)(t.QuadPart - dxgi.qpc_init) / dxgi.qpc_freq; -} - -void gfx_dxgi_create_factory_and_device(bool debug, int d3d_version, bool (*create_device_fn)(IDXGIAdapter1 *adapter, bool test_only)) { - if (dxgi.CreateDXGIFactory2 != nullptr) { - ThrowIfFailed(dxgi.CreateDXGIFactory2(debug ? DXGI_CREATE_FACTORY_DEBUG : 0, __uuidof(IDXGIFactory2), &dxgi.factory)); - } else { - ThrowIfFailed(dxgi.CreateDXGIFactory1(__uuidof(IDXGIFactory2), &dxgi.factory)); - } - - ComPtr adapter; - for (UINT i = 0; dxgi.factory->EnumAdapters1(i, &adapter) != DXGI_ERROR_NOT_FOUND; i++) { - DXGI_ADAPTER_DESC1 desc; - adapter->GetDesc1(&desc); - if (desc.Flags & 2/*DXGI_ADAPTER_FLAG_SOFTWARE*/) { // declaration missing in mingw headers - continue; - } - if (create_device_fn(adapter.Get(), true)) { - break; - } - } - create_device_fn(adapter.Get(), false); - - wchar_t w_title[512]; - int len = dxgi.window_title.length(); - mbstowcs(w_title, dxgi.window_title.c_str(), len + 1); - SetWindowTextW(dxgi.h_wnd, w_title); -} - -ComPtr gfx_dxgi_create_swap_chain(IUnknown *device) { - bool win8 = IsWindows8OrGreater(); // DXGI_SCALING_NONE is only supported on Win8 and beyond - bool dxgi_13 = dxgi.CreateDXGIFactory2 != nullptr; // DXGI 1.3 introduced waitable object - - DXGI_SWAP_CHAIN_DESC1 swap_chain_desc = {}; - swap_chain_desc.BufferCount = 2; - swap_chain_desc.Width = 0; - swap_chain_desc.Height = 0; - swap_chain_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - swap_chain_desc.Scaling = win8 ? DXGI_SCALING_NONE : DXGI_SCALING_STRETCH; - swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // Apparently this was backported to Win 7 Platform Update - swap_chain_desc.Flags = dxgi_13 ? DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT : 0; - swap_chain_desc.SampleDesc.Count = 1; - - run_as_dpi_aware([&] () { - // When setting size for the buffers, the values that DXGI puts into the desc (that can later be retrieved by GetDesc1) - // have been divided by the current scaling factor. By making this call dpi aware, no division will be performed. - // The same goes for IDXGISwapChain::ResizeBuffers(), however that function is currently only called from the message handler. - ThrowIfFailed(dxgi.factory->CreateSwapChainForHwnd(device, dxgi.h_wnd, &swap_chain_desc, nullptr, nullptr, &dxgi.swap_chain)); - }); - ThrowIfFailed(dxgi.factory->MakeWindowAssociation(dxgi.h_wnd, DXGI_MWA_NO_ALT_ENTER)); - - ComPtr swap_chain2; - if (dxgi.swap_chain->QueryInterface(__uuidof(IDXGISwapChain2), &swap_chain2) == S_OK) { - ThrowIfFailed(swap_chain2->SetMaximumFrameLatency(1)); - dxgi.waitable_object = swap_chain2->GetFrameLatencyWaitableObject(); - WaitForSingleObject(dxgi.waitable_object, INFINITE); - } else { - ComPtr device1; - ThrowIfFailed(device->QueryInterface(IID_PPV_ARGS(&device1))); - ThrowIfFailed(device1->SetMaximumFrameLatency(1)); - } - - ThrowIfFailed(dxgi.swap_chain->GetDesc1(&swap_chain_desc)); - dxgi.current_width = swap_chain_desc.Width; - dxgi.current_height = swap_chain_desc.Height; - - return dxgi.swap_chain; -} - -HWND gfx_dxgi_get_h_wnd(void) { - return dxgi.h_wnd; -} - -void gfx_dxgi_shutdown(void) { -} - -void ThrowIfFailed(HRESULT res) { - if (FAILED(res)) { - fprintf(stderr, "Error: 0x%08X\n", res); - throw res; - } -} - -void ThrowIfFailed(HRESULT res, HWND h_wnd, const char *message) { - if (FAILED(res)) { - char full_message[256]; - sprintf(full_message, "%s\n\nHRESULT: 0x%08X", message, res); - dxgi.showing_error = true; - MessageBox(h_wnd, full_message, "Error", MB_OK | MB_ICONERROR); - throw res; - } -} - -struct GfxWindowManagerAPI gfx_dxgi = { - gfx_dxgi_init, - gfx_dxgi_set_keyboard_callbacks, - gfx_dxgi_main_loop, - gfx_dxgi_get_dimensions, - gfx_dxgi_handle_events, - gfx_dxgi_start_frame, - gfx_dxgi_swap_buffers_begin, - gfx_dxgi_swap_buffers_end, - gfx_dxgi_get_time, - gfx_dxgi_shutdown, -}; - -#endif diff --git a/src/pc/gfx/gfx_dxgi.h b/src/pc/gfx/gfx_dxgi.h deleted file mode 100644 index 6f42474c..00000000 --- a/src/pc/gfx/gfx_dxgi.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef GFX_DXGI_H -#define GFX_DXGI_H - -#include "gfx_rendering_api.h" - -#ifdef DECLARE_GFX_DXGI_FUNCTIONS -void gfx_dxgi_create_factory_and_device(bool debug, int d3d_version, bool (*create_device_fn)(IDXGIAdapter1 *adapter, bool test_only)); -Microsoft::WRL::ComPtr gfx_dxgi_create_swap_chain(IUnknown *device); -HWND gfx_dxgi_get_h_wnd(void); -void ThrowIfFailed(HRESULT res); -void ThrowIfFailed(HRESULT res, HWND h_wnd, const char *message); -#endif - -extern struct GfxWindowManagerAPI gfx_dxgi; - -#endif diff --git a/src/pc/pc_main.c b/src/pc/pc_main.c index a4d7211a..e71b88b8 100644 --- a/src/pc/pc_main.c +++ b/src/pc/pc_main.c @@ -14,10 +14,6 @@ #include "gfx/gfx_pc.h" #include "gfx/gfx_opengl.h" -#include "gfx/gfx_direct3d11.h" -#include "gfx/gfx_direct3d12.h" - -#include "gfx/gfx_dxgi.h" #include "gfx/gfx_sdl.h" #include "audio/audio_api.h" diff --git a/textures/moon/controller/rumble_supported.rgba16.png b/textures/moon/controller/rumble_supported.rgba16.png new file mode 100644 index 0000000000000000000000000000000000000000..b771fe969fc72ac3e6057f0c6cc6f3dacfb99efa GIT binary patch literal 1945 zcmeH`=~t3z7{(t&#RU{|MW>G2sHiw;VP-Z!TJqusNM$+_?qeh6lIW?&~`D^X<9LxrOv#e~g}`9smFX zQT>>3(&4etLBbv`E3St_Gl3FB0ieA;Dv+Xpck37`GYEhp0{}{}04T`-6kY^CkPX1% zECAkk04#|iUBB=FKoAmred&;|uQfgOKzw3S8~{$EF&s`b)zzslDw@OT8+O6#rDiY% zf)XaDQ@;`$kL64!j8OyK+!irBeS~w=;))_Ij;vLJMn9JvrfL@sdZSyAlFIQHvDW{f z1eoGO)yPuK6L#eWQCkj8Kv>T{jO}(C$_SaKT{c`}5Vc$V$U_Mt*-W}d>?k-N;^w5$ z{un$l=ofCb{%BR^HO|Ijb<#F^c({k^@G#2p^X6-9t4x5D>Fv` zKmvLoYdc&v0J=aI2CPwI!?|xUpOqwefg)FrqY{axQc-Z`(N$Raza~-55G{anI9h?0zx# zO=ryC{XeSY+(SY&b#--Ou~;gVc6N4lb;0WDS0jg+nwpxOg*E$5%|{rOO7-OzU+rrH z|GR-VldkF;&`qZ9Ndv$@rXEC%ZN$Np~q>H z2ZJEJox{Q_X*pb`F zl7tygTutd#j9+!dvlm1&MM#^~yxjt%;H;X-BKW})zBuu!7UD*k$nN;VL25H~A>+nus|dt1C*RgK?r>nUP+nC3@p#FpwVXxL<#ZX#q7f||eO+VHbGK4kU} z&RSZ$vO1d5m49UCQh8Ma_C^hswfXJR%DP2IqF~kBlKNfBxt^uPw}o|+d$}VjO|+@h z>|`sQ5$Vdvs!beQdaaB+nx08w=b}!veq$an9q9E;=jV=7Zqh%glNxn@T*E9+`&i1n z54cqC4QiloJTD4E8`XN(hL3J3>F;SFV8t^-PUA1c){V4)g6!~0|C?vs^j=>`Di?{m zoB#TKBHbMsf!})ZfwL4UT{RXhccXsj8HqA4U{z@b3!-+VAzn4Ld5l3KZwbzHbx7|n zC`4VRShc$8;r%rSPFmC-5%xWFa6$6H_!Zp5V{K#E{z$&z8PgbZqI6BOR-L@y5c!uj$t4SVh zzNzJ2(OkeMDJ_@rka+BVz&)FrD5VRAebDgi=