New cvars: r_renderAPI , r_renderAPICompareWindow.

r_renderAPI specifies rendering API to use (0 - opengl, 1 - vulkan).
r_renderAPICompareWindow shows additional window which does the same rendering as the main windows but uses different graphics API.
The idea is to use r_renderAPICompareWindow for debugging to be sure that both APIs render identical/similar pictures.
This commit is contained in:
Artem Kharytoniuk 2017-03-30 17:39:48 +03:00
parent dd372cad1b
commit e9b972d562
10 changed files with 355 additions and 245 deletions

View File

@ -1,7 +1,7 @@
Removed cvars:
* r_allowExtensions
* r_allowExtensions (always use extensions if available)
* r_allowSoftwareGL
* r_colorbits (use desktop color depth by default)
* r_ext_multitexture (mandatory feature)
* r_colorbits (use desktop color depth)
* r_ext_multitexture (required)
* r_maskMinidriver
* r_primitives (always use qglDrawElements)

View File

@ -35,8 +35,6 @@ typedef struct
HINSTANCE hinstOpenGL; // HINSTANCE for the OpenGL library
qboolean pixelFormatSet;
int desktopBitsPixel;
int desktopWidth, desktopHeight;

View File

@ -47,13 +47,14 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "sdl/SDL.h"
#include "sdl/SDL_syswm.h"
extern void WG_CheckHardwareGamma( void );
extern void WG_RestoreGamma( void );
#define WINDOW_CLASS_NAME "Quake 3: Arena"
#define MAIN_WINDOW_CLASS_NAME "Quake 3: Arena"
#define API_COMPARE_WINDOW_CLASS_NAME "Quake 3: Arena [API compare]"
static qboolean s_classRegistered = qfalse;
static bool s_main_window_class_registered = false;
static bool s_api_compare_window_class_registered = false;
//
// function declaration
@ -202,7 +203,7 @@ static int GLW_ChoosePixelFormat(HDC hDC, const PIXELFORMATDESCRIPTOR *pPFD)
return bestMatch;
}
static bool GLW_SetPixelFormat(PIXELFORMATDESCRIPTOR *pPFD, int colorbits, int depthbits, int stencilbits, qboolean stereo) {
static bool GLW_SetPixelFormat(HDC hdc, PIXELFORMATDESCRIPTOR *pPFD, int colorbits, int depthbits, int stencilbits, qboolean stereo) {
const PIXELFORMATDESCRIPTOR pfd_base =
{
sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
@ -237,92 +238,85 @@ static bool GLW_SetPixelFormat(PIXELFORMATDESCRIPTOR *pPFD, int colorbits, int d
pPFD->dwFlags |= PFD_STEREO;
}
int pixelformat = GLW_ChoosePixelFormat(glw_state.hDC, pPFD);
int pixelformat = GLW_ChoosePixelFormat(hdc, pPFD);
if (pixelformat == 0) {
ri.Printf( PRINT_ALL, "...GLW_ChoosePixelFormat failed\n");
return false;
}
ri.Printf( PRINT_ALL, "...PIXELFORMAT %d selected\n", pixelformat );
DescribePixelFormat( glw_state.hDC, pixelformat, sizeof( *pPFD ), pPFD );
if (SetPixelFormat( glw_state.hDC, pixelformat, pPFD ) == FALSE) {
ri.Printf (PRINT_ALL, "...SetPixelFormat failed\n", glw_state.hDC);
DescribePixelFormat(hdc, pixelformat, sizeof( *pPFD ), pPFD);
if (SetPixelFormat(hdc, pixelformat, pPFD ) == FALSE) {
ri.Printf (PRINT_ALL, "...SetPixelFormat failed\n", hdc);
return false;
}
return true;
}
// Sets pixel format and creates opengl context.
static qboolean GLW_InitDriver() {
// Sets pixel format and creates opengl context for the given window.
static qboolean GLW_InitDriver(HWND hwnd) {
ri.Printf( PRINT_ALL, "Initializing OpenGL driver\n" );
//
// get a DC for our window if we don't already have one allocated
//
if (glw_state.hDC == NULL) {
ri.Printf( PRINT_ALL, "...getting DC: " );
glw_state.hDC = NULL;
glw_state.hGLRC = NULL;
glw_state.hDC = GetDC(g_wv.hWnd);
if (glw_state.hDC == NULL ) {
ri.Printf( PRINT_ALL, "failed\n" );
return qfalse;
}
ri.Printf( PRINT_ALL, "succeeded\n" );
//
// get a DC for our window
//
ri.Printf(PRINT_ALL, "...getting DC: ");
HDC hdc = GetDC(hwnd);
if (hdc == NULL) {
ri.Printf(PRINT_ALL, "failed\n");
return qfalse;
}
int colorbits = glw_state.desktopBitsPixel;
int depthbits = (r_depthbits->integer == 0) ? 24 : r_depthbits->integer;
int stencilbits = r_stencilbits->integer;
ri.Printf(PRINT_ALL, "succeeded\n");
//
// set pixel format
//
int colorbits = glw_state.desktopBitsPixel;
int depthbits = (r_depthbits->integer == 0) ? 24 : r_depthbits->integer;
int stencilbits = r_stencilbits->integer;
PIXELFORMATDESCRIPTOR pfd;
if (!glw_state.pixelFormatSet) {
if (!GLW_SetPixelFormat(hdc, &pfd, colorbits, depthbits, stencilbits, (qboolean)r_stereo->integer)) {
ReleaseDC(hwnd, hdc);
ri.Printf(PRINT_ALL, "...failed to find an appropriate PIXELFORMAT\n");
return qfalse;
}
if (!GLW_SetPixelFormat(&pfd, colorbits, depthbits, stencilbits, (qboolean)r_stereo->integer)) {
ReleaseDC(g_wv.hWnd, glw_state.hDC);
glw_state.hDC = NULL;
ri.Printf(PRINT_ALL, "...failed to find an appropriate PIXELFORMAT\n");
return qfalse;
}
// report if stereo is desired but unavailable
if (!(pfd.dwFlags & PFD_STEREO) && (r_stereo->integer != 0)) {
ri.Printf(PRINT_ALL, "...failed to select stereo pixel format\n");
}
glw_state.pixelFormatSet = qtrue;
// report if stereo is desired but unavailable
if (!(pfd.dwFlags & PFD_STEREO) && (r_stereo->integer != 0)) {
ri.Printf(PRINT_ALL, "...failed to select stereo pixel format\n");
}
//
// startup the OpenGL subsystem by creating a context and making it current
//
if (!glw_state.hGLRC) {
ri.Printf(PRINT_ALL, "...creating GL context: ");
glw_state.hGLRC = qwglCreateContext(glw_state.hDC);
if (glw_state.hGLRC == NULL) {
ri.Printf(PRINT_ALL, "failed\n");
return qfalse;
}
ri.Printf(PRINT_ALL, "succeeded\n");
ri.Printf(PRINT_ALL, "...making context current: ");
if (!qwglMakeCurrent(glw_state.hDC, glw_state.hGLRC)) {
qwglDeleteContext(glw_state.hGLRC);
glw_state.hGLRC = NULL;
ri.Printf(PRINT_ALL, "failed\n");
return qfalse;
}
ri.Printf(PRINT_ALL, "succeeded\n");
ri.Printf(PRINT_ALL, "...creating GL context: ");
HGLRC hglrc = qwglCreateContext(hdc);
if (hglrc == NULL) {
ReleaseDC(hwnd, hdc);
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);
ri.Printf(PRINT_ALL, "failed\n");
return qfalse;
}
ri.Printf(PRINT_ALL, "succeeded\n");
//
// store PFD specifics
// 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;
@ -331,12 +325,12 @@ static qboolean GLW_InitDriver() {
return qtrue;
}
static void GLW_CreateWindow(int width, int height, qboolean fullscreen)
static HWND create_main_window(int width, int height, qboolean fullscreen)
{
//
// register the window class if necessary
//
if ( !s_classRegistered )
if (!s_main_window_class_registered)
{
WNDCLASS wc;
@ -351,99 +345,183 @@ static void GLW_CreateWindow(int width, int height, qboolean fullscreen)
wc.hCursor = LoadCursor (NULL,IDC_ARROW);
wc.hbrBackground = (HBRUSH) (void *)COLOR_GRAYTEXT;
wc.lpszMenuName = 0;
wc.lpszClassName = WINDOW_CLASS_NAME;
wc.lpszClassName = MAIN_WINDOW_CLASS_NAME;
if ( !RegisterClass( &wc ) )
{
ri.Error( ERR_FATAL, "GLW_CreateWindow: could not register window class" );
ri.Error( ERR_FATAL, "create_main_window: could not register window class" );
}
s_classRegistered = qtrue;
s_main_window_class_registered = true;
ri.Printf( PRINT_ALL, "...registered window class\n" );
}
//
// create the HWND if one does not already exist
// compute width and height
//
if ( !g_wv.hWnd )
RECT r;
r.left = 0;
r.top = 0;
r.right = width;
r.bottom = height;
int stylebits;
if ( fullscreen )
{
//
// compute width and height
//
RECT r;
r.left = 0;
r.top = 0;
r.right = width;
r.bottom = height;
int stylebits;
if ( fullscreen )
{
stylebits = WS_POPUP|WS_VISIBLE|WS_SYSMENU;
}
else
{
stylebits = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_VISIBLE | WS_SYSMENU;
AdjustWindowRect (&r, stylebits, FALSE);
}
int w = r.right - r.left;
int h = r.bottom - r.top;
int x, y;
if ( fullscreen )
{
x = 0;
y = 0;
}
else
{
cvar_t* vid_xpos = ri.Cvar_Get ("vid_xpos", "", 0);
cvar_t* vid_ypos = ri.Cvar_Get ("vid_ypos", "", 0);
x = vid_xpos->integer;
y = vid_ypos->integer;
// adjust window coordinates if necessary
// so that the window is completely on screen
if ( x < 0 )
x = 0;
if ( y < 0 )
y = 0;
if ( w < glw_state.desktopWidth &&
h < glw_state.desktopHeight )
{
if ( x + w > glw_state.desktopWidth )
x = ( glw_state.desktopWidth - w );
if ( y + h > glw_state.desktopHeight )
y = ( glw_state.desktopHeight - h );
}
}
g_wv.hWnd = CreateWindowEx (
0,
WINDOW_CLASS_NAME,
"Quake 3: Arena",
stylebits,
x, y, w, h,
NULL,
NULL,
g_wv.hInstance,
NULL);
if ( !g_wv.hWnd )
{
ri.Error (ERR_FATAL, "GLW_CreateWindow() - Couldn't create window");
}
ShowWindow( g_wv.hWnd, SW_SHOW );
UpdateWindow( g_wv.hWnd );
ri.Printf( PRINT_ALL, "...created window@%d,%d (%dx%d)\n", x, y, w, h );
stylebits = WS_POPUP|WS_VISIBLE|WS_SYSMENU;
}
else
{
ri.Printf( PRINT_ALL, "...window already present, CreateWindowEx skipped\n" );
stylebits = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_VISIBLE | WS_SYSMENU;
AdjustWindowRect (&r, stylebits, FALSE);
}
int w = r.right - r.left;
int h = r.bottom - r.top;
int x, y;
if ( fullscreen )
{
x = 0;
y = 0;
}
else
{
cvar_t* vid_xpos = ri.Cvar_Get ("vid_xpos", "", 0);
cvar_t* vid_ypos = ri.Cvar_Get ("vid_ypos", "", 0);
x = vid_xpos->integer;
y = vid_ypos->integer;
// adjust window coordinates if necessary
// so that the window is completely on screen
if ( x < 0 )
x = 0;
if ( y < 0 )
y = 0;
if ( w < glw_state.desktopWidth &&
h < glw_state.desktopHeight )
{
if ( x + w > glw_state.desktopWidth )
x = ( glw_state.desktopWidth - w );
if ( y + h > glw_state.desktopHeight )
y = ( glw_state.desktopHeight - h );
}
}
HWND hwnd = CreateWindowEx(
0,
MAIN_WINDOW_CLASS_NAME,
"Quake 3: Arena",
stylebits,
x, y, w, h,
NULL,
NULL,
g_wv.hInstance,
NULL);
if (!hwnd)
{
ri.Error (ERR_FATAL, "create_main_window() - Couldn't create window");
}
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
ri.Printf(PRINT_ALL, "...created window@%d,%d (%dx%d)\n", x, y, w, h);
return hwnd;
}
static HWND create_api_compare_window(int width, int height)
{
//
// register the window class if necessary
//
if (!s_api_compare_window_class_registered)
{
WNDCLASS wc;
memset( &wc, 0, sizeof( wc ) );
wc.style = 0;
wc.lpfnWndProc = DefWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = g_wv.hInstance;
wc.hIcon = LoadIcon( g_wv.hInstance, MAKEINTRESOURCE(IDI_ICON1));
wc.hCursor = LoadCursor (NULL,IDC_ARROW);
wc.hbrBackground = (HBRUSH) (void *)COLOR_GRAYTEXT;
wc.lpszMenuName = 0;
wc.lpszClassName = API_COMPARE_WINDOW_CLASS_NAME;
if ( !RegisterClass( &wc ) )
{
ri.Error( ERR_FATAL, "create_api_compare_window: could not register window class" );
}
s_api_compare_window_class_registered = true;
ri.Printf( PRINT_ALL, "...registered api compare window class\n" );
}
//
// compute width and height
//
RECT r;
r.left = 0;
r.top = 0;
r.right = width;
r.bottom = height;
int stylebits = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_VISIBLE | WS_SYSMENU;
AdjustWindowRect (&r, stylebits, FALSE);
int w = r.right - r.left;
int h = r.bottom - r.top;
cvar_t* vid_xpos = ri.Cvar_Get ("vid_xpos", "", 0);
cvar_t* vid_ypos = ri.Cvar_Get ("vid_ypos", "", 0);
int x = vid_xpos->integer + width + 5; // offset to the right of the main window
int y = vid_ypos->integer;
// adjust window coordinates if necessary
// so that the window is completely on screen
if ( x < 0 )
x = 0;
if ( y < 0 )
y = 0;
if ( w < glw_state.desktopWidth &&
h < glw_state.desktopHeight )
{
if ( x + w > glw_state.desktopWidth )
x = ( glw_state.desktopWidth - w );
if ( y + h > glw_state.desktopHeight )
y = ( glw_state.desktopHeight - h );
}
// If r_renderAPI = 0 (OpenGL) then compare window uses Vulkan API.
// If r_renderAPI = 1 (Vulkan) then compare window uses OpenGL API.
char window_name[1024];
sprintf(window_name, "%s [%s]", MAIN_WINDOW_CLASS_NAME, r_renderAPI->integer ? "OpenGL" : "Vulkan");
HWND hwnd = CreateWindowEx(
0,
API_COMPARE_WINDOW_CLASS_NAME,
window_name,
stylebits,
x, y, w, h,
NULL,
NULL,
g_wv.hInstance,
NULL);
if (!hwnd)
{
ri.Error (ERR_FATAL, "create_api_compare_window() - Couldn't create window");
}
ShowWindow(hwnd, SW_SHOW);
UpdateWindow(hwnd);
ri.Printf(PRINT_ALL, "...created api compare window@%d,%d (%dx%d)\n", x, y, w, h);
return hwnd;
}
/*
@ -474,30 +552,57 @@ static bool GLW_SetMode(int mode, qboolean fullscreen) {
glConfig.isFullscreen = fullscreen;
ri.Printf( PRINT_ALL, " %d %d %s\n", glConfig.vidWidth, glConfig.vidHeight, fullscreen ? "FS" : "W");
GLW_CreateWindow(glConfig.vidWidth, glConfig.vidHeight, fullscreen);
g_wv.hWnd = NULL;
g_wv.hWnd_opengl = NULL;
g_wv.hWnd_vulkan = NULL;
if (!GLW_InitDriver()) {
ShowWindow(g_wv.hWnd, SW_HIDE);
DestroyWindow(g_wv.hWnd);
g_wv.hWnd = NULL;
return false;
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);
if (!initialize_vulkan(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;
vulkan_demo = new Vulkan_Demo(glConfig.vidWidth, glConfig.vidHeight);
}
}
} else { // vulkan
if (!initialize_vulkan(hwnd)) {
ShowWindow(hwnd, SW_HIDE);
DestroyWindow(hwnd);
return false;
}
vulkan_demo = new Vulkan_Demo(glConfig.vidWidth, glConfig.vidHeight);
g_wv.hWnd = hwnd;
g_wv.hWnd_vulkan = hwnd;
if (r_renderAPICompareWindow->integer) {
HWND hwnd2 = create_api_compare_window(glConfig.vidWidth, glConfig.vidHeight);
if (!GLW_InitDriver(hwnd2)) {
ShowWindow(hwnd2, SW_HIDE);
DestroyWindow(hwnd2);
ri.Printf(PRINT_WARNING, "GLW_SetMode: could not create API compare window");
} else {
g_wv.hWnd_opengl = hwnd2;
}
}
}
SetForegroundWindow(g_wv.hWnd);
SetFocus(g_wv.hWnd);
// VULKAN
if (SDL_Init(SDL_INIT_VIDEO) != 0)
ri.Error(ERR_FATAL, "SDL_Init error");
SDL_Window* window = SDL_CreateWindow("Vulkan app", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
glConfig.vidWidth, glConfig.vidHeight, SDL_WINDOW_SHOWN);
if (window == nullptr)
ri.Error(ERR_FATAL, "failed to create SDL window");
SDL_SysWMinfo window_sys_info;
SDL_VERSION(&window_sys_info.version)
if (SDL_GetWindowWMInfo(window, &window_sys_info) == SDL_FALSE)
ri.Error(ERR_FATAL, "failed to get platform specific window information");
vulkan_demo = new Vulkan_Demo(glConfig.vidWidth, glConfig.vidHeight, window_sys_info);
return true;
}
@ -700,66 +805,60 @@ void GLimp_Init( void )
*/
void GLimp_Shutdown( void )
{
// const char *strings[] = { "soft", "hard" };
const char *success[] = { "failed", "success" };
int retVal;
// FIXME: Brian, we need better fallbacks from partially initialized failures
if ( !qwglMakeCurrent ) {
return;
}
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 )
{
retVal = qwglMakeCurrent( NULL, NULL ) != 0;
ri.Printf( PRINT_ALL, "...wglMakeCurrent( NULL, NULL ): %s\n", success[retVal] );
if (qwglMakeCurrent) {
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;
ri.Printf( PRINT_ALL, "...deleting GL context: %s\n", success[retVal] );
if (glw_state.hGLRC) {
retVal = qwglDeleteContext(glw_state.hGLRC) != 0;
ri.Printf(PRINT_ALL, "...deleting GL context: %s\n", success[retVal]);
glw_state.hGLRC = NULL;
}
// release DC
if ( glw_state.hDC )
{
retVal = ReleaseDC( g_wv.hWnd, glw_state.hDC ) != 0;
ri.Printf( PRINT_ALL, "...releasing DC: %s\n", success[retVal] );
glw_state.hDC = NULL;
if (glw_state.hDC) {
retVal = ReleaseDC(g_wv.hWnd_opengl, glw_state.hDC) != 0;
ri.Printf(PRINT_ALL, "...releasing DC: %s\n", success[retVal]);
glw_state.hDC = NULL;
}
// destroy window
if ( g_wv.hWnd )
{
ri.Printf( PRINT_ALL, "...destroying window\n" );
ShowWindow( g_wv.hWnd, SW_HIDE );
DestroyWindow( g_wv.hWnd );
g_wv.hWnd = NULL;
glw_state.pixelFormatSet = qfalse;
if (g_wv.hWnd_opengl) {
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;
}
g_wv.hWnd = NULL;
// close the r_logFile
if ( glw_state.log_fp )
{
fclose( glw_state.log_fp );
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 ) );
memset(&glConfig, 0, sizeof(glConfig));
memset(&glState, 0, sizeof(glState));
}
/*

View File

@ -73,7 +73,11 @@ typedef struct
HINSTANCE reflib_library; // Handle to refresh DLL
qboolean reflib_active;
HWND hWnd;
HWND hWnd; // main window, refers either to hWnd_opengl or to hWnd_vulkan
HWND hWnd_opengl;
HWND hWnd_vulkan;
HINSTANCE hInstance;
qboolean activeApp;
qboolean isMinimized;

View File

@ -28,6 +28,9 @@ glstate_t glState;
static void GfxInfo_f( void );
cvar_t *r_renderAPI;
cvar_t *r_renderAPICompareWindow;
cvar_t *r_flareSize;
cvar_t *r_flareFade;
@ -794,6 +797,9 @@ R_Register
*/
void R_Register( void )
{
r_renderAPI = ri.Cvar_Get( "r_renderAPI", "0", CVAR_ARCHIVE | CVAR_LATCH ) ;
r_renderAPICompareWindow = ri.Cvar_Get( "r_renderAPICompareWindow", "0", 0 ) ;
//
// latched and archived variables
//

View File

@ -979,6 +979,8 @@ extern Vulkan_Demo* vulkan_demo;
//
// cvars
//
extern cvar_t *r_renderAPI;
extern cvar_t *r_renderAPICompareWindow;
extern cvar_t *r_flareSize;
extern cvar_t *r_flareFade;

View File

@ -109,13 +109,13 @@ static VkPhysicalDevice select_physical_device(VkInstance instance) {
return physical_devices[0]; // just get the first one
}
static VkSurfaceKHR create_surface(VkInstance instance, const SDL_SysWMinfo& window_sys_info) {
static VkSurfaceKHR create_surface(VkInstance instance, HWND hwnd) {
VkWin32SurfaceCreateInfoKHR desc;
desc.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
desc.pNext = nullptr;
desc.flags = 0;
desc.hinstance = ::GetModuleHandle(nullptr);
desc.hwnd = window_sys_info.info.win.window;
desc.hwnd = hwnd;
VkSurfaceKHR surface;
VkResult result = vkCreateWin32SurfaceKHR(instance, &desc, nullptr, &surface);
@ -251,48 +251,53 @@ static VkSwapchainKHR create_swapchain(VkPhysicalDevice physical_device, VkDevic
return swapchain;
}
void initialize_vulkan(const SDL_SysWMinfo& window_sys_info) {
auto& g = vulkan_globals;
bool initialize_vulkan(HWND hwnd) {
try {
auto& g = vulkan_globals;
g.instance = create_instance();
g.physical_device = select_physical_device(g.instance);
g.surface = create_surface(g.instance, window_sys_info);
g.queue_family_index = select_queue_family(g.physical_device, g.surface);
g.device = create_device(g.physical_device, g.queue_family_index);
g.instance = create_instance();
g.physical_device = select_physical_device(g.instance);
g.surface = create_surface(g.instance, hwnd);
g.queue_family_index = select_queue_family(g.physical_device, g.surface);
g.device = create_device(g.physical_device, g.queue_family_index);
vkGetDeviceQueue(g.device, g.queue_family_index, 0, &g.queue);
vkGetDeviceQueue(g.device, g.queue_family_index, 0, &g.queue);
g.surface_format = select_surface_format(g.physical_device, g.surface);
g.swapchain = create_swapchain(g.physical_device, g.device, g.surface, g.surface_format);
g.surface_format = select_surface_format(g.physical_device, g.surface);
g.swapchain = create_swapchain(g.physical_device, g.device, g.surface, g.surface_format);
uint32_t image_count;
VkResult result = vkGetSwapchainImagesKHR(g.device, g.swapchain, &image_count, nullptr);
check_vk_result(result, "vkGetSwapchainImagesKHR");
g.swapchain_images.resize(image_count);
result = vkGetSwapchainImagesKHR(g.device, g.swapchain, &image_count, g.swapchain_images.data());
check_vk_result(result, "vkGetSwapchainImagesKHR");
uint32_t image_count;
VkResult result = vkGetSwapchainImagesKHR(g.device, g.swapchain, &image_count, nullptr);
check_vk_result(result, "vkGetSwapchainImagesKHR");
g.swapchain_images.resize(image_count);
result = vkGetSwapchainImagesKHR(g.device, g.swapchain, &image_count, g.swapchain_images.data());
check_vk_result(result, "vkGetSwapchainImagesKHR");
g.swapchain_image_views.resize(image_count);
for (std::size_t i = 0; i < image_count; i++) {
VkImageViewCreateInfo desc;
desc.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
desc.pNext = nullptr;
desc.flags = 0;
desc.image = g.swapchain_images[i];
desc.viewType = VK_IMAGE_VIEW_TYPE_2D;
desc.format = g.surface_format.format;
desc.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
desc.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
desc.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
desc.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
desc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
desc.subresourceRange.baseMipLevel = 0;
desc.subresourceRange.levelCount = 1;
desc.subresourceRange.baseArrayLayer = 0;
desc.subresourceRange.layerCount = 1;
result = vkCreateImageView(g.device, &desc, nullptr, &g.swapchain_image_views[i]);
check_vk_result(result, "vkCreateImageView");
g.swapchain_image_views.resize(image_count);
for (std::size_t i = 0; i < image_count; i++) {
VkImageViewCreateInfo desc;
desc.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
desc.pNext = nullptr;
desc.flags = 0;
desc.image = g.swapchain_images[i];
desc.viewType = VK_IMAGE_VIEW_TYPE_2D;
desc.format = g.surface_format.format;
desc.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
desc.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
desc.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
desc.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
desc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
desc.subresourceRange.baseMipLevel = 0;
desc.subresourceRange.levelCount = 1;
desc.subresourceRange.baseArrayLayer = 0;
desc.subresourceRange.layerCount = 1;
result = vkCreateImageView(g.device, &desc, nullptr, &g.swapchain_image_views[i]);
check_vk_result(result, "vkCreateImageView");
}
} catch (const std::exception&) {
return false;
}
return true;
}
void deinitialize_vulkan() {

View File

@ -9,9 +9,7 @@
#include <vector>
struct SDL_SysWMinfo;
void initialize_vulkan(const SDL_SysWMinfo& window_sys_info);
bool initialize_vulkan(HWND hwnd);
void deinitialize_vulkan();
VkPhysicalDevice get_physical_device();

View File

@ -111,13 +111,11 @@ static VkFormat find_depth_format(VkPhysicalDevice physical_device) {
FILE* logfile;
Vulkan_Demo::Vulkan_Demo(int window_width, int window_height, const SDL_SysWMinfo& window_sys_info)
Vulkan_Demo::Vulkan_Demo(int window_width, int window_height)
: window_width(window_width)
, window_height(window_height)
{
logfile = fopen("vk_dev.log", "w");
initialize_vulkan(window_sys_info);
get_allocator()->initialize(get_physical_device(), get_device());
get_resource_manager()->initialize(get_device());
create_command_pool();

View File

@ -11,7 +11,7 @@ struct SDL_SysWMinfo;
class Vulkan_Demo {
public:
Vulkan_Demo(int window_width, int window_height, const SDL_SysWMinfo& window_sys_info);
Vulkan_Demo(int window_width, int window_height);
~Vulkan_Demo();
void begin_frame();