diff --git a/src/engine/platform/win_glimp.c b/src/engine/platform/win_glimp.c index c27a4ef..58f5b69 100644 --- a/src/engine/platform/win_glimp.c +++ b/src/engine/platform/win_glimp.c @@ -414,11 +414,11 @@ static HWND create_main_window(int width, int height, qboolean fullscreen) strcpy(window_name, MAIN_WINDOW_CLASS_NAME); } else { const char* api_name = "invalid-render-api"; - if (r_renderAPI->integer == 0) + if (get_render_api() == RENDER_API_GL) api_name = "OpenGL"; - else if (r_renderAPI->integer == 1) + else if (get_render_api() == RENDER_API_VK) api_name = "Vulkan"; - else if (r_renderAPI->integer == 2) + else if (get_render_api() == RENDER_API_DX) api_name = "DX12"; sprintf(window_name, "%s [%s]", MAIN_WINDOW_CLASS_NAME, api_name); } @@ -445,7 +445,7 @@ static HWND create_main_window(int width, int height, qboolean fullscreen) return hwnd; } -static HWND create_twin_window(int width, int height, int render_api) +static HWND create_twin_window(int width, int height, RenderApi render_api) { // // register the window class if necessary @@ -494,15 +494,15 @@ static HWND create_twin_window(int width, int height, int render_api) cvar_t* vid_ypos = ri.Cvar_Get ("vid_ypos", "", 0); int x, y; - bool show_three_windows = (r_twinMode->integer | (1 << r_renderAPI->integer)) == 7; + bool show_three_windows = (r_twinMode->integer | (1 << get_render_api())) == 7; if (!show_three_windows) { // two windows x = vid_xpos->integer + width + 5; // offset to the right of the main window y = vid_ypos->integer; } else { // three windows bool first_twin_window = - (r_renderAPI->integer > 0 && render_api == 0) || - (r_renderAPI->integer == 0 && render_api == 1); + (get_render_api() != RENDER_API_GL && render_api == RENDER_API_GL) || + (get_render_api() == RENDER_API_GL && render_api == RENDER_API_VK); if (first_twin_window) { x = vid_xpos->integer + width + 5; @@ -529,11 +529,11 @@ static HWND create_twin_window(int width, int height, int render_api) char window_name[1024]; const char* api_name = "invalid-render-api"; - if (render_api == 0) + if (render_api == RENDER_API_GL) api_name = "OpenGL"; - else if (render_api == 1) + else if (render_api == RENDER_API_VK) api_name = "Vulkan"; - else if (render_api == 2) + else if (render_api == RENDER_API_DX) api_name = "DX12"; sprintf(window_name, "%s [%s]", MAIN_WINDOW_CLASS_NAME, api_name); @@ -752,14 +752,14 @@ void GLimp_Init( void ) SetMode(r_mode->integer, (qboolean)r_fullscreen->integer); - if (r_renderAPI->integer == 0) { + if (get_render_api() == RENDER_API_GL) { g_wv.hWnd_opengl = create_main_window(glConfig.vidWidth, glConfig.vidHeight, (qboolean)r_fullscreen->integer); g_wv.hWnd = g_wv.hWnd_opengl; SetForegroundWindow(g_wv.hWnd); SetFocus(g_wv.hWnd); WG_CheckHardwareGamma(); } else { - g_wv.hWnd_opengl = create_twin_window(glConfig.vidWidth, glConfig.vidHeight, 0); + g_wv.hWnd_opengl = create_twin_window(glConfig.vidWidth, glConfig.vidHeight, RENDER_API_GL); } if (!GLW_InitDriver(g_wv.hWnd_opengl)) { @@ -864,14 +864,14 @@ void vk_imp_init() { // Create window. SetMode(r_mode->integer, (qboolean)r_fullscreen->integer); - if (r_renderAPI->integer == 1) { + if (get_render_api() == RENDER_API_VK) { g_wv.hWnd_vulkan = create_main_window(glConfig.vidWidth, glConfig.vidHeight, (qboolean)r_fullscreen->integer); g_wv.hWnd = g_wv.hWnd_vulkan; SetForegroundWindow(g_wv.hWnd); SetFocus(g_wv.hWnd); WG_CheckHardwareGamma(); } else { - g_wv.hWnd_vulkan = create_twin_window(glConfig.vidWidth, glConfig.vidHeight, 1); + g_wv.hWnd_vulkan = create_twin_window(glConfig.vidWidth, glConfig.vidHeight, RENDER_API_VK); } } @@ -933,14 +933,14 @@ void dx_imp_init() { // Create window. SetMode(r_mode->integer, (qboolean)r_fullscreen->integer); - if (r_renderAPI->integer == 2) { + if (get_render_api() == RENDER_API_DX) { g_wv.hWnd_dx = create_main_window(glConfig.vidWidth, glConfig.vidHeight, (qboolean)r_fullscreen->integer); g_wv.hWnd = g_wv.hWnd_dx; SetForegroundWindow(g_wv.hWnd); SetFocus(g_wv.hWnd); WG_CheckHardwareGamma(); } else { - g_wv.hWnd_dx = create_twin_window(glConfig.vidWidth, glConfig.vidHeight, 2); + g_wv.hWnd_dx = create_twin_window(glConfig.vidWidth, glConfig.vidHeight, RENDER_API_DX); } } diff --git a/src/engine/renderer/dx.cpp b/src/engine/renderer/dx.cpp index d28558a..11bf1ea 100644 --- a/src/engine/renderer/dx.cpp +++ b/src/engine/renderer/dx.cpp @@ -4,9 +4,14 @@ #include #include +#ifndef DISABLE_DX12 + #include "D3d12.h" #include "DXGI1_4.h" +#pragma comment (lib, "D3d12.lib") +#pragma comment (lib, "DXGI.lib") + const int VERTEX_CHUNK_SIZE = 512 * 1024; const int XYZ_SIZE = 4 * VERTEX_CHUNK_SIZE; @@ -1479,3 +1484,23 @@ void dx_end_frame() { DX_CHECK(dx.swapchain->Present(0, 0)); } + +#else // DISABLE_DX12 + +void dx_initialize() {} +void dx_shutdown() {} +void dx_release_resources() {} +void dx_wait_device_idle() {} + +Dx_Image dx_create_image(int width, int height, Dx_Image_Format format, int mip_levels, bool repeat_texture, int image_index) { return Dx_Image{}; } +void dx_upload_image_data(ID3D12Resource* texture, int width, int height, int mip_levels, const uint8_t* pixels, int bytes_per_pixel) {} +void dx_create_sampler_descriptor(const Vk_Sampler_Def& def, Dx_Sampler_Index sampler_index) {} +ID3D12PipelineState* dx_find_pipeline(const Vk_Pipeline_Def& def) { return nullptr; } + +void dx_clear_attachments(bool clear_depth_stencil, bool clear_color, vec4_t color) {} +void dx_bind_geometry() {} +void dx_shade_geometry(ID3D12PipelineState* pipeline, bool multitexture, Vk_Depth_Range depth_range, bool indexed, bool lines) {} +void dx_begin_frame() {} +void dx_end_frame() {} + +#endif // DISABLE_DX12 diff --git a/src/engine/renderer/dx.h b/src/engine/renderer/dx.h index 9a7f4c8..c8eca6c 100644 --- a/src/engine/renderer/dx.h +++ b/src/engine/renderer/dx.h @@ -1,5 +1,8 @@ #pragma once +// Uncomment the following line to disable DX12 backend +//#define DISABLE_DX12 + struct ID3D12CommandAllocator; struct ID3D12GraphicsCommandList; struct ID3D12CommandQueue; diff --git a/src/engine/renderer/tr_init.c b/src/engine/renderer/tr_init.c index d7c2b12..d67e900 100644 --- a/src/engine/renderer/tr_init.c +++ b/src/engine/renderer/tr_init.c @@ -171,6 +171,20 @@ static void AssertCvarRange( cvar_t *cv, float minVal, float maxVal, qboolean sh } } +RenderApi get_render_api() { + if (r_renderAPI->integer == 0) + return RENDER_API_GL; + else if (r_renderAPI->integer == 1) + return RENDER_API_VK; + else if (r_renderAPI->integer == 2) +#ifndef DISABLE_DX12 + return RENDER_API_DX; +#else + return RENDER_API_GL; // use default (GL) if dx12 is disabled +#endif + else + return RENDER_API_GL; // use default (GL) if invalid r_renderAPI value is specified +} /* ** This function is responsible for initializing a valid OpenGL/Vulkan subsystem. @@ -190,8 +204,14 @@ static void InitRenderAPI( void ) // if ( glConfig.vidWidth == 0 ) { +#ifdef DISABLE_DX12 + if (r_renderAPI->integer == 2) { + ri.Printf(PRINT_WARNING, "DirectX 12 backend is disabled (code was compiled with DISABLE_DX12). OpenGL backend will be used instead.\n"); + } +#endif + // OpenGL - if (r_renderAPI->integer == 0 || (r_twinMode->integer&1)) { + if (get_render_api() == RENDER_API_GL || (r_twinMode->integer&1)) { GLimp_Init(); GLint temp; @@ -202,16 +222,18 @@ static void InitRenderAPI( void ) } // VULKAN - if (r_renderAPI->integer == 1 || (r_twinMode->integer&2)) { + if (get_render_api() == RENDER_API_VK || (r_twinMode->integer&2)) { vk_imp_init(); vk_initialize(); } // DX12 - if (r_renderAPI->integer == 2 || (r_twinMode->integer&4)) { +#ifndef DISABLE_DX12 + if (get_render_api() == RENDER_API_DX || (r_twinMode->integer&4)) { dx_imp_init(); dx_initialize(); } +#endif } // init command buffers and SMP @@ -375,9 +397,9 @@ void RB_TakeScreenshot( int x, int y, int width, int height, char *fileName ) { buffer[15] = height >> 8; buffer[16] = 24; // pixel size - if (r_renderAPI->integer == 0) { + if (get_render_api() == RENDER_API_GL) { qglReadPixels( x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer+18 ); - } else if (r_renderAPI->integer == 1) { // VULKAN + } else if (get_render_api() == RENDER_API_VK) { // VULKAN byte* buffer2 = (byte*) ri.Hunk_AllocateTempMemory(glConfig.vidWidth*glConfig.vidHeight*4); vk_read_pixels(buffer2); @@ -392,7 +414,7 @@ void RB_TakeScreenshot( int x, int y, int width, int height, char *fileName ) { buffer2_ptr += 4; } ri.Hunk_FreeTempMemory(buffer2); - } else if (r_renderAPI->integer == 2) { // DX12 + } else if (get_render_api() == RENDER_API_DX) { // DX12 ri.Printf(PRINT_WARNING, "RT_TakeScreenshot is not implemented for DX12"); } @@ -422,11 +444,11 @@ RB_TakeScreenshotJPEG void RB_TakeScreenshotJPEG( int x, int y, int width, int height, char *fileName ) { byte* buffer = (byte*) ri.Hunk_AllocateTempMemory(glConfig.vidWidth*glConfig.vidHeight*4);; - if (r_renderAPI->integer == 0) { + if (get_render_api() == RENDER_API_GL) { qglReadPixels( x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer ); - } else if (r_renderAPI->integer == 1) { // VULKAN + } else if (get_render_api() == RENDER_API_VK) { // VULKAN vk_read_pixels(buffer); - } else if (r_renderAPI->integer == 2) { // DX12 + } else if (get_render_api() == RENDER_API_DX) { // DX12 ri.Printf(PRINT_WARNING, "RT_TakeScreenshotJPEG is not implemented for DX12"); } @@ -562,9 +584,9 @@ void R_LevelShot( void ) { buffer[14] = 128; buffer[16] = 24; // pixel size - if (r_renderAPI->integer == 0) { + if (get_render_api() == RENDER_API_GL) { qglReadPixels( 0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_RGB, GL_UNSIGNED_BYTE, source ); - } else if (r_renderAPI->integer == 1) { // VULKAN + } else if (get_render_api() == RENDER_API_VK) { // VULKAN byte* buffer2 = (byte*) ri.Hunk_AllocateTempMemory(glConfig.vidWidth*glConfig.vidHeight*4); vk_read_pixels(buffer2); @@ -578,7 +600,7 @@ void R_LevelShot( void ) { buffer2_ptr += 4; } ri.Hunk_FreeTempMemory(buffer2); - } else if (r_renderAPI->integer == 2) { // DX12 + } else if (get_render_api() == RENDER_API_DX) { // DX12 ri.Printf(PRINT_WARNING, "R_LevelShot is not implemented for DX12"); } diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index e2a7b2b..ead6f61 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -945,6 +945,13 @@ extern Vk_World vk_world; // this data is cleared during ref re-init extern Dx_Instance dx; // shouldn't be cleared during ref re-init extern Dx_World dx_world; // this data is cleared during ref re-init +enum RenderApi { + RENDER_API_GL, + RENDER_API_VK, + RENDER_API_DX +}; + +RenderApi get_render_api(); // // cvars diff --git a/visual-studio/quake3.vcxproj b/visual-studio/quake3.vcxproj index 02425f9..1c08b83 100644 --- a/visual-studio/quake3.vcxproj +++ b/visual-studio/quake3.vcxproj @@ -79,7 +79,7 @@ 0x0409 - winmm.lib;wsock32.lib;D3d12.lib;DXGI.lib;d3dcompiler.lib;%(AdditionalDependencies) + winmm.lib;wsock32.lib;%(AdditionalDependencies) true true Windows @@ -120,7 +120,7 @@ 0x0409 - winmm.lib;wsock32.lib;D3d12.lib;DXGI.lib;d3dcompiler.lib;%(AdditionalDependencies) + winmm.lib;wsock32.lib;%(AdditionalDependencies) true Windows 8388608