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 );
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 );
void CG_ClearParticles (void);

View File

@ -175,9 +175,6 @@ void S_PaintChannels(int endtime);
void S_memoryLoad(sfx_t *sfx);
portable_samplepair_t *S_GetRawSamplePointer();
// spatializes a channel
void S_Spatialize(channel_t *ch);
// adpcm functions
int S_AdpcmMemoryNeeded( const wavinfo_t *info );
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
{
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;
} 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;
if (gamma_hdc == NULL)
gamma_hdc = GetDC(NULL);
ret = SetDeviceGammaRamp( gamma_hdc, table );
HDC hdc = GetDC(NULL);
ret = SetDeviceGammaRamp( hdc, table );
if ( !ret ) {
Com_Printf( "SetDeviceGammaRamp failed.\n" );
}
if (glw_state.hDC == NULL)
ReleaseDC(NULL, gamma_hdc);
ReleaseDC(NULL, hdc);
}
/*

View File

@ -23,7 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
** WIN_GLIMP.C
**
** 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:
**
** GLimp_EndFrame
@ -31,8 +31,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
** GLimp_LogComment
** GLimp_Shutdown
**
** Note that the GLW_xxx functions are Windows specific GL-subsystem
** related functions that are relevant ONLY to win_glimp.c
** vk_imp_init
** vk_imp_shutdown
*/
#include <assert.h>
#include "../renderer/tr_local.h"
@ -60,8 +60,21 @@ void QGL_Shutdown( void );
//
// variable declarations
//
static HDC gl_hdc; // handle to device context
static HGLRC gl_hglrc; // handle to GL rendering context
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
**
@ -251,15 +264,12 @@ static bool GLW_SetPixelFormat(HDC hdc, PIXELFORMATDESCRIPTOR *pPFD, int colorbi
static qboolean GLW_InitDriver(HWND hwnd) {
ri.Printf( PRINT_ALL, "Initializing OpenGL driver\n" );
glw_state.hDC = NULL;
glw_state.hGLRC = NULL;
//
// get a DC for our window
//
ri.Printf(PRINT_ALL, "...getting DC: ");
HDC hdc = GetDC(hwnd);
if (hdc == NULL) {
gl_hdc = GetDC(hwnd);
if (gl_hdc == NULL) {
ri.Printf(PRINT_ALL, "failed\n");
return qfalse;
}
@ -268,13 +278,14 @@ static qboolean GLW_InitDriver(HWND hwnd) {
//
// set pixel format
//
int colorbits = glw_state.desktopBitsPixel;
int colorbits = GetDesktopColorDepth();
int depthbits = (r_depthbits->integer == 0) ? 24 : r_depthbits->integer;
int stencilbits = r_stencilbits->integer;
PIXELFORMATDESCRIPTOR pfd;
if (!GLW_SetPixelFormat(hdc, &pfd, colorbits, depthbits, stencilbits, (qboolean)r_stereo->integer)) {
ReleaseDC(hwnd, hdc);
if (!GLW_SetPixelFormat(gl_hdc, &pfd, colorbits, depthbits, stencilbits, (qboolean)r_stereo->integer)) {
ReleaseDC(hwnd, gl_hdc);
gl_hdc = NULL;
ri.Printf(PRINT_ALL, "...failed to find an appropriate PIXELFORMAT\n");
return qfalse;
}
@ -288,34 +299,30 @@ static qboolean GLW_InitDriver(HWND hwnd) {
// startup the OpenGL subsystem by creating a context and making it current
//
ri.Printf(PRINT_ALL, "...creating GL context: ");
HGLRC hglrc = qwglCreateContext(hdc);
if (hglrc == NULL) {
ReleaseDC(hwnd, hdc);
gl_hglrc = qwglCreateContext(gl_hdc);
if (gl_hglrc == NULL) {
ReleaseDC(hwnd, gl_hdc);
gl_hdc = NULL;
ri.Printf(PRINT_ALL, "failed\n");
return qfalse;
}
ri.Printf(PRINT_ALL, "succeeded\n");
ri.Printf(PRINT_ALL, "...making context current: ");
if (!qwglMakeCurrent(hdc, hglrc)) {
qwglDeleteContext(hglrc);
ReleaseDC(hwnd, hdc);
if (!qwglMakeCurrent(gl_hdc, gl_hglrc)) {
qwglDeleteContext(gl_hglrc);
gl_hglrc = NULL;
ReleaseDC(hwnd, gl_hdc);
gl_hdc = NULL;
ri.Printf(PRINT_ALL, "failed\n");
return qfalse;
}
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.depthBits = ( int ) pfd.cDepthBits;
glConfig.stencilBits = ( int ) pfd.cStencilBits;
glConfig.stereoEnabled = (pfd.dwFlags & PFD_STEREO) ? qtrue : qfalse;
return qtrue;
}
@ -326,12 +333,16 @@ static HWND create_main_window(int width, int height, qboolean fullscreen)
//
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;
memset( &wc, 0, sizeof( wc ) );
wc.style = 0;
wc.lpfnWndProc = glw_state.wndproc;
wc.lpfnWndProc = wndproc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = g_wv.hInstance;
@ -393,13 +404,15 @@ static HWND create_main_window(int width, int height, qboolean fullscreen)
if ( y < 0 )
y = 0;
if ( w < glw_state.desktopWidth &&
h < glw_state.desktopHeight )
int desktop_width = GetDesktopWidth();
int desktop_height = GetDesktopHeight();
if (w < desktop_width && h < desktop_height)
{
if ( x + w > glw_state.desktopWidth )
x = ( glw_state.desktopWidth - w );
if ( y + h > glw_state.desktopHeight )
y = ( glw_state.desktopHeight - h );
if ( x + w > desktop_width )
x = ( desktop_width - w );
if ( y + h > desktop_height )
y = ( desktop_height - h );
}
}
@ -482,13 +495,15 @@ static HWND create_api_compare_window(int width, int height)
if ( y < 0 )
y = 0;
if ( w < glw_state.desktopWidth &&
h < glw_state.desktopHeight )
int desktop_width = GetDesktopWidth();
int desktop_height = GetDesktopHeight();
if (w < desktop_width && h < desktop_height)
{
if ( x + w > glw_state.desktopWidth )
x = ( glw_state.desktopWidth - w );
if ( y + h > glw_state.desktopHeight )
y = ( glw_state.desktopHeight - h );
if ( x + w > desktop_width )
x = ( desktop_width - w );
if ( y + h > desktop_height )
y = ( desktop_height - h );
}
// 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;
}
/*
** 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);
}
static void SetMode(int mode, qboolean fullscreen) {
if (fullscreen) {
ri.Printf( PRINT_ALL, "...setting fullscreen mode:");
glConfig.vidWidth = glw_state.desktopWidth;
glConfig.vidHeight = glw_state.desktopHeight;
glConfig.vidWidth = GetDesktopWidth();
glConfig.vidHeight = GetDesktopHeight();
glConfig.windowAspect = 1.0f;
}
else {
} else {
ri.Printf( PRINT_ALL, "...setting mode %d:", mode );
if (!R_GetModeInfo(&glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode)) {
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;
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 )
{
if (!gl_active) {
qglActiveTextureARB = [] (GLenum) {};
qglClientActiveTextureARB = [](GLenum) {};
return;
}
ri.Printf( PRINT_ALL, "Initializing OpenGL extensions\n" );
// GL_S3_s3tc
@ -731,7 +675,7 @@ void GLimp_EndFrame (void)
// don't flip if drawing to front buffer
if ( Q_stricmp( r_drawBuffer->string, "GL_FRONT" ) != 0 )
{
SwapBuffers( glw_state.hDC );
SwapBuffers( gl_hdc );
}
// check logging
@ -750,14 +694,8 @@ void GLimp_EndFrame (void)
*/
void GLimp_Init( void )
{
cvar_t *cv;
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 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");
}
// create the window and set up the context
if (!GLW_SetMode(r_mode->integer, (qboolean)r_fullscreen->integer))
{
ri.Error(ERR_FATAL, "GLW_SetMode - could not set the given mode (%d)\n", r_mode->integer);
SetMode(r_mode->integer, (qboolean)r_fullscreen->integer);
if (r_renderAPI->integer == 0) {
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
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));
@ -792,31 +740,24 @@ void GLimp_Init( void )
void GLimp_Shutdown( void )
{
const char *success[] = { "failed", "success" };
int retVal;
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) {
retVal = qwglMakeCurrent(NULL, NULL) != 0;
int retVal = qwglMakeCurrent(NULL, NULL) != 0;
ri.Printf(PRINT_ALL, "...wglMakeCurrent( NULL, NULL ): %s\n", success[retVal]);
}
// delete HGLRC
if (glw_state.hGLRC) {
retVal = qwglDeleteContext(glw_state.hGLRC) != 0;
if (gl_hglrc) {
int retVal = qwglDeleteContext(gl_hglrc) != 0;
ri.Printf(PRINT_ALL, "...deleting GL context: %s\n", success[retVal]);
glw_state.hGLRC = NULL;
gl_hglrc = NULL;
}
// release DC
if (glw_state.hDC) {
retVal = ReleaseDC(g_wv.hWnd_opengl, glw_state.hDC) != 0;
if (gl_hdc) {
int retVal = ReleaseDC(g_wv.hWnd_opengl, gl_hdc) != 0;
ri.Printf(PRINT_ALL, "...releasing DC: %s\n", success[retVal]);
glw_state.hDC = NULL;
gl_hdc = NULL;
}
// destroy window
@ -824,32 +765,26 @@ void GLimp_Shutdown( void )
ri.Printf(PRINT_ALL, "...destroying opengl window\n");
ShowWindow(g_wv.hWnd_opengl, SW_HIDE);
DestroyWindow(g_wv.hWnd_opengl);
g_wv.hWnd_opengl = NULL;
}
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;
}
if (g_wv.hWnd == g_wv.hWnd_opengl)
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) {
fclose(glw_state.log_fp);
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 )
{
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();
// 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 *data;
if ( !qwglMakeCurrent( glw_state.hDC, NULL ) ) {
if ( !qwglMakeCurrent( gl_hdc, NULL ) ) {
wglErrors++;
}
@ -926,7 +924,7 @@ void *GLimp_RendererSleep( void ) {
WaitForSingleObject( renderCommandsEvent, INFINITE );
if ( !qwglMakeCurrent( glw_state.hDC, glw_state.hGLRC ) ) {
if ( !qwglMakeCurrent( gl_hdc, gl_hglrc ) ) {
wglErrors++;
}
@ -945,7 +943,7 @@ void *GLimp_RendererSleep( void ) {
void GLimp_FrontEndSleep( void ) {
WaitForSingleObject( renderCompletedEvent, INFINITE );
if ( !qwglMakeCurrent( glw_state.hDC, glw_state.hGLRC ) ) {
if ( !qwglMakeCurrent( gl_hdc, gl_hglrc ) ) {
wglErrors++;
}
}
@ -954,7 +952,7 @@ void GLimp_FrontEndSleep( void ) {
void GLimp_WakeRenderer( void *data ) {
smpData = data;
if ( !qwglMakeCurrent( glw_state.hDC, NULL ) ) {
if ( !qwglMakeCurrent( gl_hdc, NULL ) ) {
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 "glw_win.h"
static HINSTANCE hinstOpenGL; // HINSTANCE for the OpenGL library
void QGL_EnableLogging( qboolean enable );
HGLRC ( WINAPI * qwglCreateContext)(HDC);
@ -664,15 +666,17 @@ static void APIENTRY logViewport(GLint x, GLint y, GLsizei width, GLsizei height
*/
void QGL_Shutdown( void )
{
if (gl_enabled) {
ri.Printf( PRINT_ALL, "...shutting down QGL\n" );
if ( glw_state.hinstOpenGL )
if ( hinstOpenGL )
{
ri.Printf( PRINT_ALL, "...unloading OpenGL DLL\n" );
FreeLibrary( glw_state.hinstOpenGL );
FreeLibrary( hinstOpenGL );
}
}
glw_state.hinstOpenGL = NULL;
hinstOpenGL = NULL;
qglAlphaFunc = NULL;
qglBegin = NULL;
@ -734,7 +738,7 @@ void QGL_Shutdown( void )
}
# 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
@ -747,17 +751,19 @@ void QGL_Shutdown( void )
*/
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, "...calling LoadLibrary('%s'): ", dllname );
if ( ( glw_state.hinstOpenGL = LoadLibrary( dllname ) ) == 0 )
if ( ( hinstOpenGL = LoadLibrary( dllname ) ) == 0 )
{
ri.Printf( PRINT_ALL, "failed\n" );
return qfalse;
}
ri.Printf( PRINT_ALL, "succeeded\n" );
}
qglAlphaFunc = dllAlphaFunc = (decltype(dllAlphaFunc))GPA(glAlphaFunc);
qglBegin = dllBegin = (decltype(dllBegin))GPA(glBegin);
@ -823,8 +829,10 @@ qboolean QGL_Init( const char *dllname )
qglLockArraysEXT = 0;
qglUnlockArraysEXT = 0;
if (gl_enabled) {
// check logging
QGL_EnableLogging( (qboolean) r_logFile->integer );
}
return qtrue;
}

View File

@ -64,7 +64,7 @@ void GL_Bind( image_t *image ) {
qglBindTexture (GL_TEXTURE_2D, texnum);
// VULKAN
if (vk_active) {
if (vk.active) {
VkDescriptorSet set = vk_resources.images[final_image->index].descriptor_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 );
// VULKAN
if (vk_active) {
if (vk.active) {
Vk_Image& image = vk_resources.images[tr.scratchImage[client]->index];
vkDestroyImage(vk.device, image.handle, 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 );
// VULKAN
if (vk_active) {
if (vk.active) {
const Vk_Image& image = vk_resources.images[tr.scratchImage[client]->index];
vk_upload_image_data(image.handle, cols, rows, false, data);
}

View File

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

View File

@ -29,8 +29,6 @@ glstate_t glState;
// VULKAN
Vk_Instance vk;
Vk_Resources vk_resources;
bool gl_active;
bool vk_active;
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 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.
** This function is responsible for initializing a valid OpenGL/Vulkan subsystem.
*/
static void InitOpenGL( void )
static void InitRenderAPI( void )
{
//
// initialize OS specific portions of the renderer
@ -200,8 +193,15 @@ static void InitOpenGL( void )
//
if ( glConfig.vidWidth == 0 )
{
if (gl_enabled)
GLimp_Init();
// VULKAN
if (vk_enabled) {
vk_imp_init();
vk_initialize();
}
// OpenGL driver constants
GLint temp;
qglGetIntegerv( GL_MAX_TEXTURE_SIZE, &temp );
@ -930,6 +930,7 @@ void R_Init( void ) {
Com_Memset( &tr, 0, sizeof( tr ) );
Com_Memset( &backEnd, 0, sizeof( backEnd ) );
Com_Memset( &tess, 0, sizeof( tess ) );
Com_Memset( &vk_resources, 0, sizeof( vk_resources ) );
if ( (intptr_t)tess.xyz & 15 ) {
Com_Printf( "WARNING: tess.xyz not 16 byte aligned\n" );
@ -991,10 +992,7 @@ void R_Init( void ) {
}
R_ToggleSmpFrame();
gl_active = (r_renderAPI->integer == 0 || r_renderAPICompareWindow->integer > 0);
vk_active = (r_renderAPI->integer > 0 || r_renderAPICompareWindow->integer > 0);
InitOpenGL();
InitRenderAPI();
R_InitImages();
@ -1032,13 +1030,6 @@ void RE_Shutdown( qboolean destroyWindow ) {
ri.Cmd_RemoveCommand( "modelist" );
ri.Cmd_RemoveCommand( "shaderstate" );
// VULKAN
if (vk_active) {
vk_destroy_resources();
if (destroyWindow)
vk_destroy_instance();
}
if ( tr.registered ) {
R_SyncRenderThread();
R_ShutdownCommandBuffers();
@ -1052,6 +1043,15 @@ void RE_Shutdown( qboolean destroyWindow ) {
GLimp_Shutdown();
}
// VULKAN
if (vk.active) {
vk_release_resources();
if (destroyWindow) {
vk_shutdown();
vk_imp_shutdown();
}
}
tr.registered = qfalse;
}

View File

@ -942,8 +942,6 @@ extern glstate_t glState; // outside of TR since it shouldn't be cleared during
// VULKAN
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 bool gl_active;
extern bool vk_active;
//
@ -1197,13 +1195,15 @@ IMPLEMENTATION SPECIFIC FUNCTIONS
void GLimp_Init( void );
void GLimp_Shutdown( void );
void GLimp_EndFrame( void );
void GLimp_LogComment( char *comment );
qboolean GLimp_SpawnRenderThread( void (*function)( void ) );
void *GLimp_RendererSleep( void );
void GLimp_FrontEndSleep( void );
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
// 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 );
#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;
// VULKAN
if (vk_active) {
if (vk.active) {
VkPipeline pipeline = vk.dlight_pipelines[dl->additive > 0 ? 1 : 0][tess.shader->cullType][tess.shader->polygonOffset];
vk_bind_stage_specific_resources(pipeline, false, false);
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 );
// VULKAN
if (vk_active) {
if (vk.active) {
assert(tess.shader->fogPass > 0);
VkPipeline pipeline = vk.fog_pipelines[tess.shader->fogPass - 1][tess.shader->cullType][tess.shader->polygonOffset];
vk_bind_stage_specific_resources(pipeline, false, false);
@ -767,7 +767,7 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
}
// VULKAN
if (vk_active) {
if (vk.active) {
VkPipeline pipeline = pStage->vk_pipeline;
if (backEnd.viewParms.isMirror)
pipeline = pStage->vk_mirror_pipeline;

View File

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

View File

@ -451,7 +451,7 @@ static void DrawSkyBox( shader_t *shader )
sky_maxs_subd );
// VULKAN: draw skybox side
if (vk_active) {
if (vk.active) {
VkDescriptorSet set = vk_resources.images[shader->sky.outerbox[sky_texorder[i]]->index].descriptor_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;
}
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) {
uint32_t count;
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&);
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.instance = create_instance();
vk.physical_device = select_physical_device(vk.instance);
VkPhysicalDeviceFeatures features;
@ -528,7 +525,6 @@ void vk_create_instance(HWND hwnd) {
if (features.shaderClipDistance == VK_FALSE)
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.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);
vk_log_file = nullptr;
@ -975,7 +972,7 @@ void vk_destroy_instance() {
static float pipeline_create_time;
void vk_destroy_resources() {
void vk_release_resources() {
vkDeviceWaitIdle(vk.device);
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) {
if (!vk_active)
if (!vk.active)
return;
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() {
if (!vk_active) return;
if (!vk.active) return;
// xyz
{
@ -1888,7 +1885,7 @@ void vk_bind_stage_specific_resources(VkPipeline pipeline, bool multitexture, bo
}
void vk_begin_frame() {
if (!vk_active)
if (!vk.active)
return;
if (r_logFile->integer)
@ -1931,7 +1928,7 @@ void vk_begin_frame() {
}
void vk_end_frame() {
if (!vk_active)
if (!vk.active)
return;
if (r_logFile->integer)

View File

@ -54,9 +54,20 @@ struct Vk_Image {
//
// Initialization.
//
void vk_create_instance(HWND hwnd); // initializes VK_Instance
void vk_destroy_instance(); // destroys Vk_Instance resources
void vk_destroy_resources(); // destroys Vk_Resources resources
// Creates VkInstance and stores it as Vk_Instance::instance.
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.
@ -79,6 +90,7 @@ void vk_end_frame();
// Vulkan specific structures used by the engine.
struct Vk_Instance {
bool active = false;
VkInstance instance = VK_NULL_HANDLE;
VkPhysicalDevice physical_device = VK_NULL_HANDLE;
VkSurfaceKHR surface = VK_NULL_HANDLE;