Vulkan platform specific code reorganization.

This commit is contained in:
Artem Kharytoniuk 2017-05-05 13:55:55 +03:00
parent 8ad279e5b9
commit 5a5b0b4d2b
15 changed files with 276 additions and 281 deletions

View File

@ -1539,10 +1539,6 @@ void trap_CIN_SetExtents (int handle, int x, int y, int w, int h);
void trap_SnapVector( float *v ); void trap_SnapVector( float *v );
qboolean trap_loadCamera(const char *name);
void trap_startCamera(int time);
qboolean trap_getCameraInfo(int time, vec3_t *origin, vec3_t *angles);
qboolean trap_GetEntityToken( char *buffer, int bufferSize ); qboolean trap_GetEntityToken( char *buffer, int bufferSize );
void CG_ClearParticles (void); void CG_ClearParticles (void);

View File

@ -175,9 +175,6 @@ void S_PaintChannels(int endtime);
void S_memoryLoad(sfx_t *sfx); void S_memoryLoad(sfx_t *sfx);
portable_samplepair_t *S_GetRawSamplePointer(); portable_samplepair_t *S_GetRawSamplePointer();
// spatializes a channel
void S_Spatialize(channel_t *ch);
// adpcm functions // adpcm functions
int S_AdpcmMemoryNeeded( const wavinfo_t *info ); int S_AdpcmMemoryNeeded( const wavinfo_t *info );
void S_AdpcmEncodeSound( sfx_t *sfx, short *samples ); void S_AdpcmEncodeSound( sfx_t *sfx, short *samples );

View File

@ -28,16 +28,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
typedef struct typedef struct
{ {
WNDPROC wndproc;
HDC hDC; // handle to device context
HGLRC hGLRC; // handle to GL rendering context
HINSTANCE hinstOpenGL; // HINSTANCE for the OpenGL library
int desktopBitsPixel;
int desktopWidth, desktopHeight;
FILE *log_fp; FILE *log_fp;
} glwstate_t; } glwstate_t;

View File

@ -123,18 +123,12 @@ void GLimp_SetGamma( unsigned char red[256], unsigned char green[256], unsigned
} }
} }
HDC gamma_hdc = glw_state.hDC; HDC hdc = GetDC(NULL);
if (gamma_hdc == NULL) ret = SetDeviceGammaRamp( hdc, table );
gamma_hdc = GetDC(NULL);
ret = SetDeviceGammaRamp( gamma_hdc, table );
if ( !ret ) { if ( !ret ) {
Com_Printf( "SetDeviceGammaRamp failed.\n" ); Com_Printf( "SetDeviceGammaRamp failed.\n" );
} }
ReleaseDC(NULL, hdc);
if (glw_state.hDC == NULL)
ReleaseDC(NULL, gamma_hdc);
} }
/* /*

View File

@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
** WIN_GLIMP.C ** WIN_GLIMP.C
** **
** This file contains ALL Win32 specific stuff having to do with the ** This file contains ALL Win32 specific stuff having to do with the
** OpenGL refresh. When a port is being made the following functions ** OpenGL/Vulkan refresh. When a port is being made the following functions
** must be implemented by the port: ** must be implemented by the port:
** **
** GLimp_EndFrame ** GLimp_EndFrame
@ -31,8 +31,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
** GLimp_LogComment ** GLimp_LogComment
** GLimp_Shutdown ** GLimp_Shutdown
** **
** Note that the GLW_xxx functions are Windows specific GL-subsystem ** vk_imp_init
** related functions that are relevant ONLY to win_glimp.c ** vk_imp_shutdown
*/ */
#include <assert.h> #include <assert.h>
#include "../renderer/tr_local.h" #include "../renderer/tr_local.h"
@ -60,8 +60,21 @@ void QGL_Shutdown( void );
// //
// variable declarations // variable declarations
// //
static HDC gl_hdc; // handle to device context
static HGLRC gl_hglrc; // handle to GL rendering context
glwstate_t glw_state; glwstate_t glw_state;
static int GetDesktopCaps(int index) {
HDC hdc = GetDC(GetDesktopWindow());
int value = GetDeviceCaps(hdc, index);
ReleaseDC(GetDesktopWindow(), hdc);
return value;
}
static int GetDesktopColorDepth() { return GetDesktopCaps(BITSPIXEL); }
static int GetDesktopWidth() { return GetDesktopCaps(HORZRES); }
static int GetDesktopHeight() { return GetDesktopCaps(VERTRES); }
/* /*
** ChoosePFD ** ChoosePFD
** **
@ -251,15 +264,12 @@ static bool GLW_SetPixelFormat(HDC hdc, PIXELFORMATDESCRIPTOR *pPFD, int colorbi
static qboolean GLW_InitDriver(HWND hwnd) { static qboolean GLW_InitDriver(HWND hwnd) {
ri.Printf( PRINT_ALL, "Initializing OpenGL driver\n" ); ri.Printf( PRINT_ALL, "Initializing OpenGL driver\n" );
glw_state.hDC = NULL;
glw_state.hGLRC = NULL;
// //
// get a DC for our window // get a DC for our window
// //
ri.Printf(PRINT_ALL, "...getting DC: "); ri.Printf(PRINT_ALL, "...getting DC: ");
HDC hdc = GetDC(hwnd); gl_hdc = GetDC(hwnd);
if (hdc == NULL) { if (gl_hdc == NULL) {
ri.Printf(PRINT_ALL, "failed\n"); ri.Printf(PRINT_ALL, "failed\n");
return qfalse; return qfalse;
} }
@ -268,13 +278,14 @@ static qboolean GLW_InitDriver(HWND hwnd) {
// //
// set pixel format // set pixel format
// //
int colorbits = glw_state.desktopBitsPixel; int colorbits = GetDesktopColorDepth();
int depthbits = (r_depthbits->integer == 0) ? 24 : r_depthbits->integer; int depthbits = (r_depthbits->integer == 0) ? 24 : r_depthbits->integer;
int stencilbits = r_stencilbits->integer; int stencilbits = r_stencilbits->integer;
PIXELFORMATDESCRIPTOR pfd; PIXELFORMATDESCRIPTOR pfd;
if (!GLW_SetPixelFormat(hdc, &pfd, colorbits, depthbits, stencilbits, (qboolean)r_stereo->integer)) { if (!GLW_SetPixelFormat(gl_hdc, &pfd, colorbits, depthbits, stencilbits, (qboolean)r_stereo->integer)) {
ReleaseDC(hwnd, hdc); ReleaseDC(hwnd, gl_hdc);
gl_hdc = NULL;
ri.Printf(PRINT_ALL, "...failed to find an appropriate PIXELFORMAT\n"); ri.Printf(PRINT_ALL, "...failed to find an appropriate PIXELFORMAT\n");
return qfalse; return qfalse;
} }
@ -288,34 +299,30 @@ static qboolean GLW_InitDriver(HWND hwnd) {
// startup the OpenGL subsystem by creating a context and making it current // startup the OpenGL subsystem by creating a context and making it current
// //
ri.Printf(PRINT_ALL, "...creating GL context: "); ri.Printf(PRINT_ALL, "...creating GL context: ");
HGLRC hglrc = qwglCreateContext(hdc); gl_hglrc = qwglCreateContext(gl_hdc);
if (hglrc == NULL) { if (gl_hglrc == NULL) {
ReleaseDC(hwnd, hdc); ReleaseDC(hwnd, gl_hdc);
gl_hdc = NULL;
ri.Printf(PRINT_ALL, "failed\n"); ri.Printf(PRINT_ALL, "failed\n");
return qfalse; return qfalse;
} }
ri.Printf(PRINT_ALL, "succeeded\n"); ri.Printf(PRINT_ALL, "succeeded\n");
ri.Printf(PRINT_ALL, "...making context current: "); ri.Printf(PRINT_ALL, "...making context current: ");
if (!qwglMakeCurrent(hdc, hglrc)) { if (!qwglMakeCurrent(gl_hdc, gl_hglrc)) {
qwglDeleteContext(hglrc); qwglDeleteContext(gl_hglrc);
ReleaseDC(hwnd, hdc); gl_hglrc = NULL;
ReleaseDC(hwnd, gl_hdc);
gl_hdc = NULL;
ri.Printf(PRINT_ALL, "failed\n"); ri.Printf(PRINT_ALL, "failed\n");
return qfalse; return qfalse;
} }
ri.Printf(PRINT_ALL, "succeeded\n"); ri.Printf(PRINT_ALL, "succeeded\n");
//
// update global state and return
//
glw_state.hDC = hdc;
glw_state.hGLRC = hglrc;
glConfig.colorBits = ( int ) pfd.cColorBits; glConfig.colorBits = ( int ) pfd.cColorBits;
glConfig.depthBits = ( int ) pfd.cDepthBits; glConfig.depthBits = ( int ) pfd.cDepthBits;
glConfig.stencilBits = ( int ) pfd.cStencilBits; glConfig.stencilBits = ( int ) pfd.cStencilBits;
glConfig.stereoEnabled = (pfd.dwFlags & PFD_STEREO) ? qtrue : qfalse; glConfig.stereoEnabled = (pfd.dwFlags & PFD_STEREO) ? qtrue : qfalse;
return qtrue; return qtrue;
} }
@ -326,12 +333,16 @@ static HWND create_main_window(int width, int height, qboolean fullscreen)
// //
if (!s_main_window_class_registered) if (!s_main_window_class_registered)
{ {
cvar_t* cv = ri.Cvar_Get( "win_wndproc", "", 0 );
WNDPROC wndproc;
sscanf(cv->string, "%p", (void **)&wndproc);
WNDCLASS wc; WNDCLASS wc;
memset( &wc, 0, sizeof( wc ) ); memset( &wc, 0, sizeof( wc ) );
wc.style = 0; wc.style = 0;
wc.lpfnWndProc = glw_state.wndproc; wc.lpfnWndProc = wndproc;
wc.cbClsExtra = 0; wc.cbClsExtra = 0;
wc.cbWndExtra = 0; wc.cbWndExtra = 0;
wc.hInstance = g_wv.hInstance; wc.hInstance = g_wv.hInstance;
@ -393,13 +404,15 @@ static HWND create_main_window(int width, int height, qboolean fullscreen)
if ( y < 0 ) if ( y < 0 )
y = 0; y = 0;
if ( w < glw_state.desktopWidth && int desktop_width = GetDesktopWidth();
h < glw_state.desktopHeight ) int desktop_height = GetDesktopHeight();
if (w < desktop_width && h < desktop_height)
{ {
if ( x + w > glw_state.desktopWidth ) if ( x + w > desktop_width )
x = ( glw_state.desktopWidth - w ); x = ( desktop_width - w );
if ( y + h > glw_state.desktopHeight ) if ( y + h > desktop_height )
y = ( glw_state.desktopHeight - h ); y = ( desktop_height - h );
} }
} }
@ -482,13 +495,15 @@ static HWND create_api_compare_window(int width, int height)
if ( y < 0 ) if ( y < 0 )
y = 0; y = 0;
if ( w < glw_state.desktopWidth && int desktop_width = GetDesktopWidth();
h < glw_state.desktopHeight ) int desktop_height = GetDesktopHeight();
if (w < desktop_width && h < desktop_height)
{ {
if ( x + w > glw_state.desktopWidth ) if ( x + w > desktop_width )
x = ( glw_state.desktopWidth - w ); x = ( desktop_width - w );
if ( y + h > glw_state.desktopHeight ) if ( y + h > desktop_height )
y = ( glw_state.desktopHeight - h ); y = ( desktop_height - h );
} }
// If r_renderAPI = 0 (OpenGL) then compare window uses Vulkan API. // If r_renderAPI = 0 (OpenGL) then compare window uses Vulkan API.
@ -518,86 +533,21 @@ static HWND create_api_compare_window(int width, int height)
return hwnd; return hwnd;
} }
/* static void SetMode(int mode, qboolean fullscreen) {
** GLW_SetMode
*/
static bool GLW_SetMode(int mode, qboolean fullscreen) {
{
HDC hDC = GetDC(GetDesktopWindow());
glw_state.desktopBitsPixel = GetDeviceCaps(hDC, BITSPIXEL);
glw_state.desktopWidth = GetDeviceCaps(hDC, HORZRES);
glw_state.desktopHeight = GetDeviceCaps(hDC, VERTRES);
ReleaseDC(GetDesktopWindow(), hDC);
}
if (fullscreen) { if (fullscreen) {
ri.Printf( PRINT_ALL, "...setting fullscreen mode:"); ri.Printf( PRINT_ALL, "...setting fullscreen mode:");
glConfig.vidWidth = glw_state.desktopWidth; glConfig.vidWidth = GetDesktopWidth();
glConfig.vidHeight = glw_state.desktopHeight; glConfig.vidHeight = GetDesktopHeight();
glConfig.windowAspect = 1.0f; glConfig.windowAspect = 1.0f;
} } else {
else {
ri.Printf( PRINT_ALL, "...setting mode %d:", mode ); ri.Printf( PRINT_ALL, "...setting mode %d:", mode );
if (!R_GetModeInfo(&glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode)) { if (!R_GetModeInfo(&glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode)) {
ri.Printf( PRINT_ALL, " invalid mode\n" ); ri.Printf( PRINT_ALL, " invalid mode\n" );
return false; ri.Error(ERR_FATAL, "SetMode - could not set the given mode (%d)\n", mode);
} }
} }
glConfig.isFullscreen = fullscreen; glConfig.isFullscreen = fullscreen;
ri.Printf( PRINT_ALL, " %d %d %s\n", glConfig.vidWidth, glConfig.vidHeight, fullscreen ? "FS" : "W"); ri.Printf( PRINT_ALL, " %d %d %s\n", glConfig.vidWidth, glConfig.vidHeight, fullscreen ? "FS" : "W");
g_wv.hWnd = NULL;
g_wv.hWnd_opengl = NULL;
g_wv.hWnd_vulkan = NULL;
HWND hwnd = create_main_window(glConfig.vidWidth, glConfig.vidHeight, fullscreen);
if (r_renderAPI->integer == 0) { // opengl
if (!GLW_InitDriver(hwnd)) {
ShowWindow(hwnd, SW_HIDE);
DestroyWindow(hwnd);
return false;
}
g_wv.hWnd = hwnd;
g_wv.hWnd_opengl = hwnd;
if (r_renderAPICompareWindow->integer) {
HWND hwnd2 = create_api_compare_window(glConfig.vidWidth, glConfig.vidHeight);
vk_create_instance(hwnd2);
g_wv.hWnd_vulkan = hwnd2;
/*if (!vk_initialize(hwnd2)) {
ShowWindow(hwnd2, SW_HIDE);
DestroyWindow(hwnd2);
ri.Printf(PRINT_WARNING, "GLW_SetMode: could not create API compare window");
} else {
g_wv.hWnd_vulkan = hwnd2;
}*/
}
} else { // vulkan
if (r_renderAPICompareWindow->integer) {
HWND hwnd2 = create_api_compare_window(glConfig.vidWidth, glConfig.vidHeight);
if (!GLW_InitDriver(hwnd2)) {
DestroyWindow(hwnd2);
ri.Printf(PRINT_WARNING, "GLW_SetMode: could not create API compare window");
} else {
g_wv.hWnd_opengl = hwnd2;
}
}
vk_create_instance(hwnd);
/*if (!vk_initialize(hwnd)) {
ShowWindow(hwnd, SW_HIDE);
DestroyWindow(hwnd);
return false;
}*/
g_wv.hWnd = hwnd;
g_wv.hWnd_vulkan = hwnd;
}
SetForegroundWindow(g_wv.hWnd);
SetFocus(g_wv.hWnd);
return true;
} }
/* /*
@ -605,12 +555,6 @@ static bool GLW_SetMode(int mode, qboolean fullscreen) {
*/ */
static void GLW_InitExtensions( void ) static void GLW_InitExtensions( void )
{ {
if (!gl_active) {
qglActiveTextureARB = [] (GLenum) {};
qglClientActiveTextureARB = [](GLenum) {};
return;
}
ri.Printf( PRINT_ALL, "Initializing OpenGL extensions\n" ); ri.Printf( PRINT_ALL, "Initializing OpenGL extensions\n" );
// GL_S3_s3tc // GL_S3_s3tc
@ -731,7 +675,7 @@ void GLimp_EndFrame (void)
// don't flip if drawing to front buffer // don't flip if drawing to front buffer
if ( Q_stricmp( r_drawBuffer->string, "GL_FRONT" ) != 0 ) if ( Q_stricmp( r_drawBuffer->string, "GL_FRONT" ) != 0 )
{ {
SwapBuffers( glw_state.hDC ); SwapBuffers( gl_hdc );
} }
// check logging // check logging
@ -750,14 +694,8 @@ void GLimp_EndFrame (void)
*/ */
void GLimp_Init( void ) void GLimp_Init( void )
{ {
cvar_t *cv;
ri.Printf( PRINT_ALL, "Initializing OpenGL subsystem\n" ); ri.Printf( PRINT_ALL, "Initializing OpenGL subsystem\n" );
// save wndproc
cv = ri.Cvar_Get( "win_wndproc", "", 0 );
sscanf( cv->string, "%p", (void **)&glw_state.wndproc );
// load appropriate DLL and initialize subsystem // load appropriate DLL and initialize subsystem
// //
// load the driver and bind our function pointers to it // load the driver and bind our function pointers to it
@ -767,12 +705,22 @@ void GLimp_Init( void )
ri.Error(ERR_FATAL, "QGL_Init - could not load OpenGL driver\n"); ri.Error(ERR_FATAL, "QGL_Init - could not load OpenGL driver\n");
} }
// create the window and set up the context SetMode(r_mode->integer, (qboolean)r_fullscreen->integer);
if (!GLW_SetMode(r_mode->integer, (qboolean)r_fullscreen->integer))
{ if (r_renderAPI->integer == 0) {
ri.Error(ERR_FATAL, "GLW_SetMode - could not set the given mode (%d)\n", r_mode->integer); g_wv.hWnd_opengl = create_main_window(glConfig.vidWidth, glConfig.vidHeight, (qboolean)r_fullscreen->integer);
g_wv.hWnd = g_wv.hWnd_opengl;
} else {
g_wv.hWnd_opengl = create_api_compare_window(glConfig.vidWidth, glConfig.vidHeight);
} }
if (!GLW_InitDriver(g_wv.hWnd_opengl)) {
ri.Error(ERR_FATAL, "GLW_InitDriver - could not initialize OpenGL subsystem\n");
}
SetForegroundWindow(g_wv.hWnd);
SetFocus(g_wv.hWnd);
// get our config strings // get our config strings
Q_strncpyz( glConfig.vendor_string, (const char*) qglGetString (GL_VENDOR), sizeof( glConfig.vendor_string ) ); Q_strncpyz( glConfig.vendor_string, (const char*) qglGetString (GL_VENDOR), sizeof( glConfig.vendor_string ) );
Q_strncpyz(glConfig.renderer_string, (const char*)qglGetString(GL_RENDERER), sizeof(glConfig.renderer_string)); Q_strncpyz(glConfig.renderer_string, (const char*)qglGetString(GL_RENDERER), sizeof(glConfig.renderer_string));
@ -792,31 +740,24 @@ void GLimp_Init( void )
void GLimp_Shutdown( void ) void GLimp_Shutdown( void )
{ {
const char *success[] = { "failed", "success" }; const char *success[] = { "failed", "success" };
int retVal;
ri.Printf(PRINT_ALL, "Shutting down OpenGL subsystem\n"); ri.Printf(PRINT_ALL, "Shutting down OpenGL subsystem\n");
// restore gamma. We do this first because 3Dfx's extension needs a valid OGL subsystem
WG_RestoreGamma();
// set current context to NULL
if (qwglMakeCurrent) { if (qwglMakeCurrent) {
retVal = qwglMakeCurrent(NULL, NULL) != 0; int retVal = qwglMakeCurrent(NULL, NULL) != 0;
ri.Printf(PRINT_ALL, "...wglMakeCurrent( NULL, NULL ): %s\n", success[retVal]); ri.Printf(PRINT_ALL, "...wglMakeCurrent( NULL, NULL ): %s\n", success[retVal]);
} }
// delete HGLRC if (gl_hglrc) {
if (glw_state.hGLRC) { int retVal = qwglDeleteContext(gl_hglrc) != 0;
retVal = qwglDeleteContext(glw_state.hGLRC) != 0;
ri.Printf(PRINT_ALL, "...deleting GL context: %s\n", success[retVal]); ri.Printf(PRINT_ALL, "...deleting GL context: %s\n", success[retVal]);
glw_state.hGLRC = NULL; gl_hglrc = NULL;
} }
// release DC if (gl_hdc) {
if (glw_state.hDC) { int retVal = ReleaseDC(g_wv.hWnd_opengl, gl_hdc) != 0;
retVal = ReleaseDC(g_wv.hWnd_opengl, glw_state.hDC) != 0;
ri.Printf(PRINT_ALL, "...releasing DC: %s\n", success[retVal]); ri.Printf(PRINT_ALL, "...releasing DC: %s\n", success[retVal]);
glw_state.hDC = NULL; gl_hdc = NULL;
} }
// destroy window // destroy window
@ -824,32 +765,26 @@ void GLimp_Shutdown( void )
ri.Printf(PRINT_ALL, "...destroying opengl window\n"); ri.Printf(PRINT_ALL, "...destroying opengl window\n");
ShowWindow(g_wv.hWnd_opengl, SW_HIDE); ShowWindow(g_wv.hWnd_opengl, SW_HIDE);
DestroyWindow(g_wv.hWnd_opengl); DestroyWindow(g_wv.hWnd_opengl);
g_wv.hWnd_opengl = NULL;
} if (g_wv.hWnd == g_wv.hWnd_opengl)
if (g_wv.hWnd_vulkan) {
ri.Printf(PRINT_ALL, "...destroying vulkan window\n");
ShowWindow(g_wv.hWnd_vulkan, SW_HIDE);
DestroyWindow(g_wv.hWnd_vulkan);
g_wv.hWnd_vulkan = NULL;
}
g_wv.hWnd = NULL; g_wv.hWnd = NULL;
// close the r_logFile g_wv.hWnd_opengl = NULL;
}
QGL_Shutdown();
WG_RestoreGamma();
memset(&glConfig, 0, sizeof(glConfig));
memset(&glState, 0, sizeof(glState));
if (glw_state.log_fp) { if (glw_state.log_fp) {
fclose(glw_state.log_fp); fclose(glw_state.log_fp);
glw_state.log_fp = 0; glw_state.log_fp = 0;
} }
// shutdown QGL subsystem
QGL_Shutdown();
memset(&glConfig, 0, sizeof(glConfig));
memset(&glState, 0, sizeof(glState));
} }
/*
** GLimp_LogComment
*/
void GLimp_LogComment( char *comment ) void GLimp_LogComment( char *comment )
{ {
if ( glw_state.log_fp ) { if ( glw_state.log_fp ) {
@ -857,6 +792,69 @@ void GLimp_LogComment( char *comment )
} }
} }
void vk_imp_init() {
ri.Printf(PRINT_ALL, "Initializing Vulkan subsystem\n");
if (!gl_enabled) {
QGL_Init(nullptr); // this will set qgl pointers to no-op placeholders
qglActiveTextureARB = [] (GLenum) {};
qglClientActiveTextureARB = [](GLenum) {};
}
SetMode(r_mode->integer, (qboolean)r_fullscreen->integer);
if (r_renderAPI->integer != 0) {
g_wv.hWnd_vulkan = create_main_window(glConfig.vidWidth, glConfig.vidHeight, (qboolean)r_fullscreen->integer);
g_wv.hWnd = g_wv.hWnd_vulkan;
} else {
g_wv.hWnd_vulkan = create_api_compare_window(glConfig.vidWidth, glConfig.vidHeight);
}
// In order to create surface we need to create VkInstance first.
vk_create_instance();
// Create VkSurfaceKHR for Win32 platform.
VkWin32SurfaceCreateInfoKHR desc;
desc.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
desc.pNext = nullptr;
desc.flags = 0;
desc.hinstance = ::GetModuleHandle(nullptr);
desc.hwnd = g_wv.hWnd_vulkan;
VK_CHECK(vkCreateWin32SurfaceKHR(vk.instance, &desc, nullptr, &vk.surface));
SetForegroundWindow(g_wv.hWnd);
SetFocus(g_wv.hWnd);
WG_CheckHardwareGamma();
}
void vk_imp_shutdown() {
ri.Printf(PRINT_ALL, "Shutting down Vulkan subsystem\n");
if (g_wv.hWnd_vulkan) {
ri.Printf(PRINT_ALL, "...destroying vulkan window\n");
DestroyWindow(g_wv.hWnd_vulkan);
if (g_wv.hWnd == g_wv.hWnd_vulkan)
g_wv.hWnd = NULL;
g_wv.hWnd_vulkan = NULL;
}
// For vulkan mode we still have qgl pointers initialized with placeholder values.
// Thus reset them the same way as we do in opengl mode.
QGL_Shutdown();
WG_RestoreGamma();
memset(&glConfig, 0, sizeof(glConfig));
memset(&glState, 0, sizeof(glState));
if (glw_state.log_fp) {
fclose(glw_state.log_fp);
glw_state.log_fp = 0;
}
}
/* /*
=========================================================== ===========================================================
@ -876,7 +874,7 @@ void GLimp_RenderThreadWrapper( void ) {
glimpRenderThread(); glimpRenderThread();
// unbind the context before we die // unbind the context before we die
qwglMakeCurrent( glw_state.hDC, NULL ); qwglMakeCurrent( gl_hdc, NULL );
} }
/* /*
@ -915,7 +913,7 @@ static int wglErrors;
void *GLimp_RendererSleep( void ) { void *GLimp_RendererSleep( void ) {
void *data; void *data;
if ( !qwglMakeCurrent( glw_state.hDC, NULL ) ) { if ( !qwglMakeCurrent( gl_hdc, NULL ) ) {
wglErrors++; wglErrors++;
} }
@ -926,7 +924,7 @@ void *GLimp_RendererSleep( void ) {
WaitForSingleObject( renderCommandsEvent, INFINITE ); WaitForSingleObject( renderCommandsEvent, INFINITE );
if ( !qwglMakeCurrent( glw_state.hDC, glw_state.hGLRC ) ) { if ( !qwglMakeCurrent( gl_hdc, gl_hglrc ) ) {
wglErrors++; wglErrors++;
} }
@ -945,7 +943,7 @@ void *GLimp_RendererSleep( void ) {
void GLimp_FrontEndSleep( void ) { void GLimp_FrontEndSleep( void ) {
WaitForSingleObject( renderCompletedEvent, INFINITE ); WaitForSingleObject( renderCompletedEvent, INFINITE );
if ( !qwglMakeCurrent( glw_state.hDC, glw_state.hGLRC ) ) { if ( !qwglMakeCurrent( gl_hdc, gl_hglrc ) ) {
wglErrors++; wglErrors++;
} }
} }
@ -954,7 +952,7 @@ void GLimp_FrontEndSleep( void ) {
void GLimp_WakeRenderer( void *data ) { void GLimp_WakeRenderer( void *data ) {
smpData = data; smpData = data;
if ( !qwglMakeCurrent( glw_state.hDC, NULL ) ) { if ( !qwglMakeCurrent( gl_hdc, NULL ) ) {
wglErrors++; wglErrors++;
} }

View File

@ -32,6 +32,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "../renderer/tr_local.h" #include "../renderer/tr_local.h"
#include "glw_win.h" #include "glw_win.h"
static HINSTANCE hinstOpenGL; // HINSTANCE for the OpenGL library
void QGL_EnableLogging( qboolean enable ); void QGL_EnableLogging( qboolean enable );
HGLRC ( WINAPI * qwglCreateContext)(HDC); HGLRC ( WINAPI * qwglCreateContext)(HDC);
@ -664,15 +666,17 @@ static void APIENTRY logViewport(GLint x, GLint y, GLsizei width, GLsizei height
*/ */
void QGL_Shutdown( void ) void QGL_Shutdown( void )
{ {
if (gl_enabled) {
ri.Printf( PRINT_ALL, "...shutting down QGL\n" ); ri.Printf( PRINT_ALL, "...shutting down QGL\n" );
if ( glw_state.hinstOpenGL ) if ( hinstOpenGL )
{ {
ri.Printf( PRINT_ALL, "...unloading OpenGL DLL\n" ); ri.Printf( PRINT_ALL, "...unloading OpenGL DLL\n" );
FreeLibrary( glw_state.hinstOpenGL ); FreeLibrary( hinstOpenGL );
}
} }
glw_state.hinstOpenGL = NULL; hinstOpenGL = NULL;
qglAlphaFunc = NULL; qglAlphaFunc = NULL;
qglBegin = NULL; qglBegin = NULL;
@ -734,7 +738,7 @@ void QGL_Shutdown( void )
} }
# pragma warning (disable : 4113 4133 4047 ) # pragma warning (disable : 4113 4133 4047 )
# define GPA( a ) (gl_active ? (void*)GetProcAddress(glw_state.hinstOpenGL, #a) : (void*)(&no ## a)) # define GPA( a ) (gl_enabled ? (void*)GetProcAddress(hinstOpenGL, #a) : (void*)(&no ## a))
/* /*
** QGL_Init ** QGL_Init
@ -747,17 +751,19 @@ void QGL_Shutdown( void )
*/ */
qboolean QGL_Init( const char *dllname ) qboolean QGL_Init( const char *dllname )
{ {
assert( glw_state.hinstOpenGL == 0 ); if (gl_enabled) {
assert( hinstOpenGL == 0 );
ri.Printf( PRINT_ALL, "...initializing QGL\n" ); ri.Printf( PRINT_ALL, "...initializing QGL\n" );
ri.Printf( PRINT_ALL, "...calling LoadLibrary('%s'): ", dllname ); ri.Printf( PRINT_ALL, "...calling LoadLibrary('%s'): ", dllname );
if ( ( glw_state.hinstOpenGL = LoadLibrary( dllname ) ) == 0 ) if ( ( hinstOpenGL = LoadLibrary( dllname ) ) == 0 )
{ {
ri.Printf( PRINT_ALL, "failed\n" ); ri.Printf( PRINT_ALL, "failed\n" );
return qfalse; return qfalse;
} }
ri.Printf( PRINT_ALL, "succeeded\n" ); ri.Printf( PRINT_ALL, "succeeded\n" );
}
qglAlphaFunc = dllAlphaFunc = (decltype(dllAlphaFunc))GPA(glAlphaFunc); qglAlphaFunc = dllAlphaFunc = (decltype(dllAlphaFunc))GPA(glAlphaFunc);
qglBegin = dllBegin = (decltype(dllBegin))GPA(glBegin); qglBegin = dllBegin = (decltype(dllBegin))GPA(glBegin);
@ -823,8 +829,10 @@ qboolean QGL_Init( const char *dllname )
qglLockArraysEXT = 0; qglLockArraysEXT = 0;
qglUnlockArraysEXT = 0; qglUnlockArraysEXT = 0;
if (gl_enabled) {
// check logging // check logging
QGL_EnableLogging( (qboolean) r_logFile->integer ); QGL_EnableLogging( (qboolean) r_logFile->integer );
}
return qtrue; return qtrue;
} }

View File

@ -64,7 +64,7 @@ void GL_Bind( image_t *image ) {
qglBindTexture (GL_TEXTURE_2D, texnum); qglBindTexture (GL_TEXTURE_2D, texnum);
// VULKAN // VULKAN
if (vk_active) { if (vk.active) {
VkDescriptorSet set = vk_resources.images[final_image->index].descriptor_set; VkDescriptorSet set = vk_resources.images[final_image->index].descriptor_set;
vk_resources.current_descriptor_sets[glState.currenttmu] = set; vk_resources.current_descriptor_sets[glState.currenttmu] = set;
} }
@ -711,7 +711,7 @@ void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
// VULKAN // VULKAN
if (vk_active) { if (vk.active) {
Vk_Image& image = vk_resources.images[tr.scratchImage[client]->index]; Vk_Image& image = vk_resources.images[tr.scratchImage[client]->index];
vkDestroyImage(vk.device, image.handle, nullptr); vkDestroyImage(vk.device, image.handle, nullptr);
vkDestroyImageView(vk.device, image.view, nullptr); vkDestroyImageView(vk.device, image.view, nullptr);
@ -727,7 +727,7 @@ void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int
qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data ); qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data );
// VULKAN // VULKAN
if (vk_active) { if (vk.active) {
const Vk_Image& image = vk_resources.images[tr.scratchImage[client]->index]; const Vk_Image& image = vk_resources.images[tr.scratchImage[client]->index];
vk_upload_image_data(image.handle, cols, rows, false, data); vk_upload_image_data(image.handle, cols, rows, false, data);
} }

View File

@ -145,7 +145,7 @@ void GL_TextureMode( const char *string ) {
} }
// VULKAN // VULKAN
if (vk_active) { if (vk.active) {
VK_CHECK(vkDeviceWaitIdle(vk.device)); VK_CHECK(vkDeviceWaitIdle(vk.device));
for ( i = 0 ; i < tr.numImages ; i++ ) { for ( i = 0 ; i < tr.numImages ; i++ ) {
image_t* glt = tr.images[i]; image_t* glt = tr.images[i];
@ -722,7 +722,7 @@ static void Upload32( unsigned *data,
done: done:
// VULKAN // VULKAN
if (vk_active) { if (vk.active) {
image = vk_create_image(*pUploadWidth, *pUploadHeight, miplevel + 1, repeat_texture); image = vk_create_image(*pUploadWidth, *pUploadHeight, miplevel + 1, repeat_texture);
vk_upload_image_data(image.handle, *pUploadWidth, *pUploadHeight, mipmap == qtrue, mipmap_buffer); vk_upload_image_data(image.handle, *pUploadWidth, *pUploadHeight, mipmap == qtrue, mipmap_buffer);
} }

View File

@ -29,8 +29,6 @@ glstate_t glState;
// VULKAN // VULKAN
Vk_Instance vk; Vk_Instance vk;
Vk_Resources vk_resources; Vk_Resources vk_resources;
bool gl_active;
bool vk_active;
static void GfxInfo_f( void ); static void GfxInfo_f( void );
@ -178,14 +176,9 @@ static void AssertCvarRange( cvar_t *cv, float minVal, float maxVal, qboolean sh
/* /*
** InitOpenGL ** This function is responsible for initializing a valid OpenGL/Vulkan subsystem.
**
** This function is responsible for initializing a valid OpenGL subsystem. This
** is done by calling GLimp_Init (which gives us a working OGL subsystem) then
** setting variables, checking GL constants, and reporting the gfx system config
** to the user.
*/ */
static void InitOpenGL( void ) static void InitRenderAPI( void )
{ {
// //
// initialize OS specific portions of the renderer // initialize OS specific portions of the renderer
@ -200,8 +193,15 @@ static void InitOpenGL( void )
// //
if ( glConfig.vidWidth == 0 ) if ( glConfig.vidWidth == 0 )
{ {
if (gl_enabled)
GLimp_Init(); GLimp_Init();
// VULKAN
if (vk_enabled) {
vk_imp_init();
vk_initialize();
}
// OpenGL driver constants // OpenGL driver constants
GLint temp; GLint temp;
qglGetIntegerv( GL_MAX_TEXTURE_SIZE, &temp ); qglGetIntegerv( GL_MAX_TEXTURE_SIZE, &temp );
@ -930,6 +930,7 @@ void R_Init( void ) {
Com_Memset( &tr, 0, sizeof( tr ) ); Com_Memset( &tr, 0, sizeof( tr ) );
Com_Memset( &backEnd, 0, sizeof( backEnd ) ); Com_Memset( &backEnd, 0, sizeof( backEnd ) );
Com_Memset( &tess, 0, sizeof( tess ) ); Com_Memset( &tess, 0, sizeof( tess ) );
Com_Memset( &vk_resources, 0, sizeof( vk_resources ) );
if ( (intptr_t)tess.xyz & 15 ) { if ( (intptr_t)tess.xyz & 15 ) {
Com_Printf( "WARNING: tess.xyz not 16 byte aligned\n" ); Com_Printf( "WARNING: tess.xyz not 16 byte aligned\n" );
@ -991,10 +992,7 @@ void R_Init( void ) {
} }
R_ToggleSmpFrame(); R_ToggleSmpFrame();
gl_active = (r_renderAPI->integer == 0 || r_renderAPICompareWindow->integer > 0); InitRenderAPI();
vk_active = (r_renderAPI->integer > 0 || r_renderAPICompareWindow->integer > 0);
InitOpenGL();
R_InitImages(); R_InitImages();
@ -1032,13 +1030,6 @@ void RE_Shutdown( qboolean destroyWindow ) {
ri.Cmd_RemoveCommand( "modelist" ); ri.Cmd_RemoveCommand( "modelist" );
ri.Cmd_RemoveCommand( "shaderstate" ); ri.Cmd_RemoveCommand( "shaderstate" );
// VULKAN
if (vk_active) {
vk_destroy_resources();
if (destroyWindow)
vk_destroy_instance();
}
if ( tr.registered ) { if ( tr.registered ) {
R_SyncRenderThread(); R_SyncRenderThread();
R_ShutdownCommandBuffers(); R_ShutdownCommandBuffers();
@ -1052,6 +1043,15 @@ void RE_Shutdown( qboolean destroyWindow ) {
GLimp_Shutdown(); GLimp_Shutdown();
} }
// VULKAN
if (vk.active) {
vk_release_resources();
if (destroyWindow) {
vk_shutdown();
vk_imp_shutdown();
}
}
tr.registered = qfalse; tr.registered = qfalse;
} }

View File

@ -942,8 +942,6 @@ extern glstate_t glState; // outside of TR since it shouldn't be cleared during
// VULKAN // VULKAN
extern Vk_Instance vk; // shouldn't be cleared during ref re-init extern Vk_Instance vk; // shouldn't be cleared during ref re-init
extern Vk_Resources vk_resources; // this data is cleared during ref re-init extern Vk_Resources vk_resources; // this data is cleared during ref re-init
extern bool gl_active;
extern bool vk_active;
// //
@ -1197,13 +1195,15 @@ IMPLEMENTATION SPECIFIC FUNCTIONS
void GLimp_Init( void ); void GLimp_Init( void );
void GLimp_Shutdown( void ); void GLimp_Shutdown( void );
void GLimp_EndFrame( void ); void GLimp_EndFrame( void );
void GLimp_LogComment( char *comment );
qboolean GLimp_SpawnRenderThread( void (*function)( void ) ); qboolean GLimp_SpawnRenderThread( void (*function)( void ) );
void *GLimp_RendererSleep( void ); void *GLimp_RendererSleep( void );
void GLimp_FrontEndSleep( void ); void GLimp_FrontEndSleep( void );
void GLimp_WakeRenderer( void *data ); void GLimp_WakeRenderer( void *data );
void GLimp_LogComment( char *comment ); void vk_imp_init();
void vk_imp_shutdown();
// NOTE TTimo linux works with float gamma value, not the gamma table // NOTE TTimo linux works with float gamma value, not the gamma table
// the params won't be used, getting the r_gamma cvar directly // the params won't be used, getting the r_gamma cvar directly
@ -1422,6 +1422,9 @@ void RB_CalcDiffuseColor( unsigned char *colors );
void myGlMultMatrix( const float *a, const float *b, float *out ); void myGlMultMatrix( const float *a, const float *b, float *out );
#define gl_enabled (r_renderAPI->integer == 0 || r_renderAPICompareWindow->integer)
#define vk_enabled (r_renderAPI->integer != 0 || r_renderAPICompareWindow->integer)
/* /*
============================================================= =============================================================

View File

@ -362,7 +362,7 @@ static void ProjectDlightTexture( void ) {
backEnd.pc.c_dlightIndexes += numIndexes; backEnd.pc.c_dlightIndexes += numIndexes;
// VULKAN // VULKAN
if (vk_active) { if (vk.active) {
VkPipeline pipeline = vk.dlight_pipelines[dl->additive > 0 ? 1 : 0][tess.shader->cullType][tess.shader->polygonOffset]; VkPipeline pipeline = vk.dlight_pipelines[dl->additive > 0 ? 1 : 0][tess.shader->cullType][tess.shader->polygonOffset];
vk_bind_stage_specific_resources(pipeline, false, false); vk_bind_stage_specific_resources(pipeline, false, false);
vkCmdDrawIndexed(vk.command_buffer, tess.numIndexes, 1, 0, 0, 0); vkCmdDrawIndexed(vk.command_buffer, tess.numIndexes, 1, 0, 0, 0);
@ -408,7 +408,7 @@ static void RB_FogPass( void ) {
R_DrawElements( tess.numIndexes, tess.indexes ); R_DrawElements( tess.numIndexes, tess.indexes );
// VULKAN // VULKAN
if (vk_active) { if (vk.active) {
assert(tess.shader->fogPass > 0); assert(tess.shader->fogPass > 0);
VkPipeline pipeline = vk.fog_pipelines[tess.shader->fogPass - 1][tess.shader->cullType][tess.shader->polygonOffset]; VkPipeline pipeline = vk.fog_pipelines[tess.shader->fogPass - 1][tess.shader->cullType][tess.shader->polygonOffset];
vk_bind_stage_specific_resources(pipeline, false, false); vk_bind_stage_specific_resources(pipeline, false, false);
@ -767,7 +767,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
} }
// VULKAN // VULKAN
if (vk_active) { if (vk.active) {
VkPipeline pipeline = pStage->vk_pipeline; VkPipeline pipeline = pStage->vk_pipeline;
if (backEnd.viewParms.isMirror) if (backEnd.viewParms.isMirror)
pipeline = pStage->vk_mirror_pipeline; pipeline = pStage->vk_mirror_pipeline;

View File

@ -2161,7 +2161,7 @@ static shader_t *FinishShader( void ) {
} }
// VULKAN: create pipelines for each shader stage // VULKAN: create pipelines for each shader stage
if (vk_active) { if (vk.active) {
Vk_Pipeline_Def def; Vk_Pipeline_Def def;
def.face_culling = shader.cullType; def.face_culling = shader.cullType;
def.polygon_offset = (shader.polygonOffset == qtrue); def.polygon_offset = (shader.polygonOffset == qtrue);

View File

@ -451,7 +451,7 @@ static void DrawSkyBox( shader_t *shader )
sky_maxs_subd ); sky_maxs_subd );
// VULKAN: draw skybox side // VULKAN: draw skybox side
if (vk_active) { if (vk.active) {
VkDescriptorSet set = vk_resources.images[shader->sky.outerbox[sky_texorder[i]]->index].descriptor_set; VkDescriptorSet set = vk_resources.images[shader->sky.outerbox[sky_texorder[i]]->index].descriptor_set;
vk_resources.current_descriptor_sets[0] = set; vk_resources.current_descriptor_sets[0] = set;

View File

@ -95,33 +95,6 @@ static uint32_t select_queue_family(VkPhysicalDevice physical_device, VkSurfaceK
return -1; return -1;
} }
static VkInstance create_instance() {
uint32_t count = 0;
VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr));
std::vector<VkExtensionProperties> extension_properties(count);
VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &count, extension_properties.data()));
for (auto name : instance_extensions) {
if (!is_extension_available(extension_properties, name))
ri.Error(ERR_FATAL, "Vulkan error: required instance extension is not available: %s", name);
}
VkInstanceCreateInfo desc;
desc.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
desc.pNext = nullptr;
desc.flags = 0;
desc.pApplicationInfo = nullptr;
desc.enabledLayerCount = 0;
desc.ppEnabledLayerNames = nullptr;
desc.enabledExtensionCount = static_cast<uint32_t>(instance_extensions.size());
desc.ppEnabledExtensionNames = instance_extensions.data();
VkInstance instance;
VK_CHECK(vkCreateInstance(&desc, nullptr, &instance));
return instance;
}
static VkPhysicalDevice select_physical_device(VkInstance instance) { static VkPhysicalDevice select_physical_device(VkInstance instance) {
uint32_t count; uint32_t count;
VK_CHECK(vkEnumeratePhysicalDevices(instance, &count, nullptr)); VK_CHECK(vkEnumeratePhysicalDevices(instance, &count, nullptr));
@ -517,10 +490,34 @@ static void ensure_staging_buffer_allocation(VkDeviceSize size) {
VkPipeline create_pipeline(const Vk_Pipeline_Def&); VkPipeline create_pipeline(const Vk_Pipeline_Def&);
void vk_create_instance(HWND hwnd) { void vk_create_instance() {
uint32_t count = 0;
VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr));
std::vector<VkExtensionProperties> extension_properties(count);
VK_CHECK(vkEnumerateInstanceExtensionProperties(nullptr, &count, extension_properties.data()));
for (auto name : instance_extensions) {
if (!is_extension_available(extension_properties, name))
ri.Error(ERR_FATAL, "Vulkan error: required instance extension is not available: %s", name);
}
VkInstanceCreateInfo desc;
desc.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
desc.pNext = nullptr;
desc.flags = 0;
desc.pApplicationInfo = nullptr;
desc.enabledLayerCount = 0;
desc.ppEnabledLayerNames = nullptr;
desc.enabledExtensionCount = static_cast<uint32_t>(instance_extensions.size());
desc.ppEnabledExtensionNames = instance_extensions.data();
VK_CHECK(vkCreateInstance(&desc, nullptr, &vk.instance));
}
void vk_initialize() {
vk_log_file = fopen("vk_dev.log", "w"); vk_log_file = fopen("vk_dev.log", "w");
vk.instance = create_instance();
vk.physical_device = select_physical_device(vk.instance); vk.physical_device = select_physical_device(vk.instance);
VkPhysicalDeviceFeatures features; VkPhysicalDeviceFeatures features;
@ -528,7 +525,6 @@ void vk_create_instance(HWND hwnd) {
if (features.shaderClipDistance == VK_FALSE) if (features.shaderClipDistance == VK_FALSE)
ri.Error(ERR_FATAL, "vk_create_instance: shaderClipDistance feature is not supported"); ri.Error(ERR_FATAL, "vk_create_instance: shaderClipDistance feature is not supported");
vk.surface = create_surface(vk.instance, hwnd);
vk.surface_format = select_surface_format(vk.physical_device, vk.surface); vk.surface_format = select_surface_format(vk.physical_device, vk.surface);
vk.queue_family_index = select_queue_family(vk.physical_device, vk.surface); vk.queue_family_index = select_queue_family(vk.physical_device, vk.surface);
@ -919,9 +915,10 @@ void vk_create_instance(HWND hwnd) {
} }
} }
} }
vk.active = true;
} }
void vk_destroy_instance() { void vk_shutdown() {
fclose(vk_log_file); fclose(vk_log_file);
vk_log_file = nullptr; vk_log_file = nullptr;
@ -975,7 +972,7 @@ void vk_destroy_instance() {
static float pipeline_create_time; static float pipeline_create_time;
void vk_destroy_resources() { void vk_release_resources() {
vkDeviceWaitIdle(vk.device); vkDeviceWaitIdle(vk.device);
auto& res = vk_resources; auto& res = vk_resources;
@ -1620,7 +1617,7 @@ VkPipeline vk_find_pipeline(const Vk_Pipeline_Def& def) {
} }
void vk_clear_attachments(bool clear_stencil, bool fast_sky) { void vk_clear_attachments(bool clear_stencil, bool fast_sky) {
if (!vk_active) if (!vk.active)
return; return;
if (!vk_resources.dirty_attachments && !fast_sky) if (!vk_resources.dirty_attachments && !fast_sky)
@ -1755,7 +1752,7 @@ static void get_mvp_transform(float* mvp) {
} }
void vk_bind_resources_shared_between_stages() { void vk_bind_resources_shared_between_stages() {
if (!vk_active) return; if (!vk.active) return;
// xyz // xyz
{ {
@ -1888,7 +1885,7 @@ void vk_bind_stage_specific_resources(VkPipeline pipeline, bool multitexture, bo
} }
void vk_begin_frame() { void vk_begin_frame() {
if (!vk_active) if (!vk.active)
return; return;
if (r_logFile->integer) if (r_logFile->integer)
@ -1931,7 +1928,7 @@ void vk_begin_frame() {
} }
void vk_end_frame() { void vk_end_frame() {
if (!vk_active) if (!vk.active)
return; return;
if (r_logFile->integer) if (r_logFile->integer)

View File

@ -54,9 +54,20 @@ struct Vk_Image {
// //
// Initialization. // Initialization.
// //
void vk_create_instance(HWND hwnd); // initializes VK_Instance
void vk_destroy_instance(); // destroys Vk_Instance resources // Creates VkInstance and stores it as Vk_Instance::instance.
void vk_destroy_resources(); // destroys Vk_Resources resources void vk_create_instance();
// Initializes VK_Instance structure.
// After calling this function we get fully functional vulkan subsystem.
void vk_initialize();
// Shutdown vulkan subsystem by releasing resources acquired by Vk_Instance.
void vk_shutdown();
// Releases vulkan resources allocated during program execution.
// This effectively puts vulkan subsystem into initial state (the state we have after vk_initialize call).
void vk_release_resources();
// //
// Resources allocation. // Resources allocation.
@ -79,6 +90,7 @@ void vk_end_frame();
// Vulkan specific structures used by the engine. // Vulkan specific structures used by the engine.
struct Vk_Instance { struct Vk_Instance {
bool active = false;
VkInstance instance = VK_NULL_HANDLE; VkInstance instance = VK_NULL_HANDLE;
VkPhysicalDevice physical_device = VK_NULL_HANDLE; VkPhysicalDevice physical_device = VK_NULL_HANDLE;
VkSurfaceKHR surface = VK_NULL_HANDLE; VkSurfaceKHR surface = VK_NULL_HANDLE;