Functionality to make proper behavior of r_renderAPI: disables current API, enables selected API.

This commit is contained in:
Artem Kharytoniuk 2017-05-03 19:08:54 +03:00
parent 2f75ace0c9
commit 8ad279e5b9
12 changed files with 372 additions and 261 deletions

View File

@ -91,7 +91,7 @@ void GLimp_SetGamma( unsigned char red[256], unsigned char green[256], unsigned
int i, j; int i, j;
int ret; int ret;
if ( !glConfig.deviceSupportsGamma || r_ignorehwgamma->integer || !glw_state.hDC ) { if ( !glConfig.deviceSupportsGamma || r_ignorehwgamma->integer ) {
return; return;
} }
@ -123,10 +123,18 @@ void GLimp_SetGamma( unsigned char red[256], unsigned char green[256], unsigned
} }
} }
ret = SetDeviceGammaRamp( glw_state.hDC, table ); HDC gamma_hdc = glw_state.hDC;
if (gamma_hdc == NULL)
gamma_hdc = GetDC(NULL);
ret = SetDeviceGammaRamp( gamma_hdc, table );
if ( !ret ) { if ( !ret ) {
Com_Printf( "SetDeviceGammaRamp failed.\n" ); Com_Printf( "SetDeviceGammaRamp failed.\n" );
} }
if (glw_state.hDC == NULL)
ReleaseDC(NULL, gamma_hdc);
} }
/* /*

View File

@ -574,6 +574,16 @@ static bool GLW_SetMode(int mode, qboolean fullscreen) {
}*/ }*/
} }
} else { // vulkan } 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); vk_create_instance(hwnd);
/*if (!vk_initialize(hwnd)) { /*if (!vk_initialize(hwnd)) {
ShowWindow(hwnd, SW_HIDE); ShowWindow(hwnd, SW_HIDE);
@ -583,17 +593,6 @@ static bool GLW_SetMode(int mode, qboolean fullscreen) {
g_wv.hWnd = hwnd; g_wv.hWnd = hwnd;
g_wv.hWnd_vulkan = 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); SetForegroundWindow(g_wv.hWnd);
@ -606,6 +605,12 @@ 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
@ -745,7 +750,6 @@ void GLimp_EndFrame (void)
*/ */
void GLimp_Init( void ) void GLimp_Init( void )
{ {
cvar_t *lastValidRenderer = ri.Cvar_Get( "r_lastValidRenderer", "(uninitialized)", CVAR_ARCHIVE );
cvar_t *cv; cvar_t *cv;
ri.Printf( PRINT_ALL, "Initializing OpenGL subsystem\n" ); ri.Printf( PRINT_ALL, "Initializing OpenGL subsystem\n" );
@ -775,19 +779,6 @@ void GLimp_Init( void )
Q_strncpyz(glConfig.version_string, (const char*)qglGetString(GL_VERSION), sizeof(glConfig.version_string)); Q_strncpyz(glConfig.version_string, (const char*)qglGetString(GL_VERSION), sizeof(glConfig.version_string));
Q_strncpyz(glConfig.extensions_string, (const char*)qglGetString(GL_EXTENSIONS), sizeof(glConfig.extensions_string)); Q_strncpyz(glConfig.extensions_string, (const char*)qglGetString(GL_EXTENSIONS), sizeof(glConfig.extensions_string));
//
// NOTE: if changing cvars, do it within this block. This allows them
// to be overridden when testing driver fixes, etc. but only sets
// them to their default state when the hardware is first installed/run.
//
if ( Q_stricmp( lastValidRenderer->string, glConfig.renderer_string ) )
{
ri.Cvar_Set( "r_textureMode", "GL_LINEAR_MIPMAP_NEAREST" );
ri.Cvar_Set("r_picmip", "1");
}
ri.Cvar_Set( "r_lastValidRenderer", glConfig.renderer_string );
GLW_InitExtensions(); GLW_InitExtensions();
WG_CheckHardwareGamma(); WG_CheckHardwareGamma();
} }

View File

@ -147,6 +147,80 @@ static void ( APIENTRY * dllVertex3fv )(const GLfloat *v);
static void ( APIENTRY * dllVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); static void ( APIENTRY * dllVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
static void ( APIENTRY * dllViewport )(GLint x, GLint y, GLsizei width, GLsizei height); static void ( APIENTRY * dllViewport )(GLint x, GLint y, GLsizei width, GLsizei height);
//
// Placeholder functions to replace OpenGL calls when Vulkan renderer is active.
//
static HGLRC nowglCreateContext(HDC) { return NULL;}
static BOOL nowglDeleteContext(HGLRC) { return FALSE; }
static PROC nowglGetProcAddress(LPCSTR) { return NULL; }
static BOOL nowglMakeCurrent(HDC, HGLRC) { return FALSE; }
static int nowglSwapIntervalEXT( int interval ) { return -1; }
static void noglActiveTextureARB ( GLenum texture ) {}
static void noglClientActiveTextureARB ( GLenum texture ) {}
static void noglLockArraysEXT (GLint, GLint) {}
static void noglUnlockArraysEXT (void) {}
static void noglAlphaFunc(GLenum func, GLclampf ref) {}
static void noglBegin(GLenum mode) {}
static void noglBindTexture(GLenum target, GLuint texture) {}
static void noglBlendFunc(GLenum sfactor, GLenum dfactor) {}
static void noglClear(GLbitfield mask) {}
static void noglClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {}
static void noglClipPlane(GLenum plane, const GLdouble *equation) {}
static void noglColor3f(GLfloat red, GLfloat green, GLfloat blue) {}
static void noglColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {}
static void noglColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {}
static void noglCullFace(GLenum mode) {}
static void noglDeleteTextures(GLsizei n, const GLuint *textures) {}
static void noglDepthFunc(GLenum func) {}
static void noglDepthMask(GLboolean flag) {}
static void noglDepthRange(GLclampd zNear, GLclampd zFar) {}
static void noglDisable(GLenum cap) {}
static void noglDisableClientState(GLenum array) {}
static void noglDrawBuffer(GLenum mode) {}
static void noglDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) {}
static void noglEnable(GLenum cap) {}
static void noglEnableClientState(GLenum array) {}
static void noglEnd(void) {}
static void noglFinish(void) {}
static GLenum noglGetError(void) { return GL_NO_ERROR; }
static void noglGetIntegerv(GLenum pname, GLint *params) {
if (pname == GL_MAX_TEXTURE_SIZE) {
*params = 2048;
}
}
static const GLubyte* noglGetString(GLenum name) { static char* s = ""; return (GLubyte*)s;}
static void noglLineWidth(GLfloat width) {}
static void noglLoadIdentity(void) {}
static void noglLoadMatrixf(const GLfloat *m) {}
static void noglMatrixMode(GLenum mode) {}
static void noglOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar) {}
static void noglPolygonMode(GLenum face, GLenum mode) {}
static void noglPolygonOffset(GLfloat factor, GLfloat units) {}
static void noglPopMatrix(void) {}
static void noglPushMatrix(void) {}
static void noglReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels) {}
static void noglScissor(GLint x, GLint y, GLsizei width, GLsizei height) {}
static void noglStencilFunc(GLenum func, GLint ref, GLuint mask) {}
static void noglStencilOp(GLenum fail, GLenum zfail, GLenum zpass) {}
static void noglTexCoord2f(GLfloat s, GLfloat t) {}
static void noglTexCoord2fv(const GLfloat *v) {}
static void noglTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {}
static void noglTexEnvf(GLenum target, GLenum pname, GLfloat param) {}
static void noglTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) {}
static void noglTexParameterf(GLenum target, GLenum pname, GLfloat param) {}
static void noglTexParameterfv(GLenum target, GLenum pname, const GLfloat *params) {}
static void noglTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) {}
static void noglVertex2f(GLfloat x, GLfloat y) {}
static void noglVertex3f(GLfloat x, GLfloat y, GLfloat z) {}
static void noglVertex3fv(const GLfloat *v) {}
static void noglVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {}
static void noglViewport(GLint x, GLint y, GLsizei width, GLsizei height) {}
static const char * BooleanToString( GLboolean b ) static const char * BooleanToString( GLboolean b )
{ {
if ( b == GL_FALSE ) if ( b == GL_FALSE )
@ -659,10 +733,8 @@ void QGL_Shutdown( void )
qwglMakeCurrent = NULL; qwglMakeCurrent = NULL;
} }
#define GR_NUM_BOARDS 0x0f
# pragma warning (disable : 4113 4133 4047 ) # pragma warning (disable : 4113 4133 4047 )
# define GPA( a ) GetProcAddress( glw_state.hinstOpenGL, a ) # define GPA( a ) (gl_active ? (void*)GetProcAddress(glw_state.hinstOpenGL, #a) : (void*)(&no ## a))
/* /*
** QGL_Init ** QGL_Init
@ -687,63 +759,63 @@ qboolean QGL_Init( const char *dllname )
} }
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);
qglBindTexture = dllBindTexture = (decltype(dllBindTexture))GPA("glBindTexture"); qglBindTexture = dllBindTexture = (decltype(dllBindTexture))GPA(glBindTexture);
qglBlendFunc = dllBlendFunc = (decltype(dllBlendFunc))GPA("glBlendFunc"); qglBlendFunc = dllBlendFunc = (decltype(dllBlendFunc))GPA(glBlendFunc);
qglClear = dllClear = (decltype(dllClear))GPA("glClear"); qglClear = dllClear = (decltype(dllClear))GPA(glClear);
qglClearColor = dllClearColor = (decltype(dllClearColor))GPA("glClearColor"); qglClearColor = dllClearColor = (decltype(dllClearColor))GPA(glClearColor);
qglClipPlane = dllClipPlane = (decltype(dllClipPlane))GPA("glClipPlane"); qglClipPlane = dllClipPlane = (decltype(dllClipPlane))GPA(glClipPlane);
qglColor3f = dllColor3f = (decltype(dllColor3f))GPA("glColor3f"); qglColor3f = dllColor3f = (decltype(dllColor3f))GPA(glColor3f);
qglColorMask = dllColorMask = (decltype(dllColorMask))GPA("glColorMask"); qglColorMask = dllColorMask = (decltype(dllColorMask))GPA(glColorMask);
qglColorPointer = dllColorPointer = (decltype(dllColorPointer))GPA("glColorPointer"); qglColorPointer = dllColorPointer = (decltype(dllColorPointer))GPA(glColorPointer);
qglCullFace = dllCullFace = (decltype(dllCullFace))GPA("glCullFace"); qglCullFace = dllCullFace = (decltype(dllCullFace))GPA(glCullFace);
qglDeleteTextures = dllDeleteTextures = (decltype(dllDeleteTextures))GPA("glDeleteTextures"); qglDeleteTextures = dllDeleteTextures = (decltype(dllDeleteTextures))GPA(glDeleteTextures);
qglDepthFunc = dllDepthFunc = (decltype(dllDepthFunc))GPA("glDepthFunc"); qglDepthFunc = dllDepthFunc = (decltype(dllDepthFunc))GPA(glDepthFunc);
qglDepthMask = dllDepthMask = (decltype(dllDepthMask))GPA("glDepthMask"); qglDepthMask = dllDepthMask = (decltype(dllDepthMask))GPA(glDepthMask);
qglDepthRange = dllDepthRange = (decltype(dllDepthRange))GPA("glDepthRange"); qglDepthRange = dllDepthRange = (decltype(dllDepthRange))GPA(glDepthRange);
qglDisable = dllDisable = (decltype(dllDisable))GPA("glDisable"); qglDisable = dllDisable = (decltype(dllDisable))GPA(glDisable);
qglDisableClientState = dllDisableClientState = (decltype(dllDisableClientState))GPA("glDisableClientState"); qglDisableClientState = dllDisableClientState = (decltype(dllDisableClientState))GPA(glDisableClientState);
qglDrawBuffer = dllDrawBuffer = (decltype(dllDrawBuffer))GPA("glDrawBuffer"); qglDrawBuffer = dllDrawBuffer = (decltype(dllDrawBuffer))GPA(glDrawBuffer);
qglDrawElements = dllDrawElements = (decltype(dllDrawElements))GPA("glDrawElements"); qglDrawElements = dllDrawElements = (decltype(dllDrawElements))GPA(glDrawElements);
qglEnable = dllEnable = (decltype(dllEnable))GPA("glEnable"); qglEnable = dllEnable = (decltype(dllEnable))GPA(glEnable);
qglEnableClientState = dllEnableClientState = (decltype(dllEnableClientState))GPA("glEnableClientState"); qglEnableClientState = dllEnableClientState = (decltype(dllEnableClientState))GPA(glEnableClientState);
qglEnd = dllEnd = (decltype(dllEnd))GPA("glEnd"); qglEnd = dllEnd = (decltype(dllEnd))GPA(glEnd);
qglFinish = dllFinish = (decltype(dllFinish))GPA("glFinish"); qglFinish = dllFinish = (decltype(dllFinish))GPA(glFinish);
qglGetError = dllGetError = ( GLenum (__stdcall * )(void) ) GPA( "glGetError" ); qglGetError = dllGetError = ( GLenum (__stdcall * )(void) ) GPA( glGetError );
qglGetIntegerv = dllGetIntegerv = (decltype(dllGetIntegerv))GPA("glGetIntegerv"); qglGetIntegerv = dllGetIntegerv = (decltype(dllGetIntegerv))GPA(glGetIntegerv);
qglGetString = dllGetString = (decltype(dllGetString))GPA("glGetString"); qglGetString = dllGetString = (decltype(dllGetString))GPA(glGetString);
qglLineWidth = dllLineWidth = (decltype(dllLineWidth))GPA("glLineWidth"); qglLineWidth = dllLineWidth = (decltype(dllLineWidth))GPA(glLineWidth);
qglLoadIdentity = dllLoadIdentity = (decltype(dllLoadIdentity))GPA("glLoadIdentity"); qglLoadIdentity = dllLoadIdentity = (decltype(dllLoadIdentity))GPA(glLoadIdentity);
qglLoadMatrixf = dllLoadMatrixf = (decltype(dllLoadMatrixf))GPA("glLoadMatrixf"); qglLoadMatrixf = dllLoadMatrixf = (decltype(dllLoadMatrixf))GPA(glLoadMatrixf);
qglMatrixMode = dllMatrixMode = (decltype(dllMatrixMode))GPA("glMatrixMode"); qglMatrixMode = dllMatrixMode = (decltype(dllMatrixMode))GPA(glMatrixMode);
qglOrtho = dllOrtho = (decltype(dllOrtho))GPA("glOrtho"); qglOrtho = dllOrtho = (decltype(dllOrtho))GPA(glOrtho);
qglPolygonMode = dllPolygonMode = (decltype(dllPolygonMode))GPA("glPolygonMode"); qglPolygonMode = dllPolygonMode = (decltype(dllPolygonMode))GPA(glPolygonMode);
qglPolygonOffset = dllPolygonOffset = (decltype(dllPolygonOffset))GPA("glPolygonOffset"); qglPolygonOffset = dllPolygonOffset = (decltype(dllPolygonOffset))GPA(glPolygonOffset);
qglPopMatrix = dllPopMatrix = (decltype(dllPopMatrix))GPA("glPopMatrix"); qglPopMatrix = dllPopMatrix = (decltype(dllPopMatrix))GPA(glPopMatrix);
qglPushMatrix = dllPushMatrix = (decltype(dllPushMatrix))GPA("glPushMatrix"); qglPushMatrix = dllPushMatrix = (decltype(dllPushMatrix))GPA(glPushMatrix);
qglReadPixels = dllReadPixels = (decltype(dllReadPixels))GPA("glReadPixels"); qglReadPixels = dllReadPixels = (decltype(dllReadPixels))GPA(glReadPixels);
qglScissor = dllScissor = (decltype(dllScissor))GPA("glScissor"); qglScissor = dllScissor = (decltype(dllScissor))GPA(glScissor);
qglStencilFunc = dllStencilFunc = (decltype(dllStencilFunc))GPA("glStencilFunc"); qglStencilFunc = dllStencilFunc = (decltype(dllStencilFunc))GPA(glStencilFunc);
qglStencilOp = dllStencilOp = (decltype(dllStencilOp))GPA("glStencilOp"); qglStencilOp = dllStencilOp = (decltype(dllStencilOp))GPA(glStencilOp);
qglTexCoord2f = dllTexCoord2f = (decltype(dllTexCoord2f))GPA("glTexCoord2f"); qglTexCoord2f = dllTexCoord2f = (decltype(dllTexCoord2f))GPA(glTexCoord2f);
qglTexCoord2fv = dllTexCoord2fv = (decltype(dllTexCoord2fv))GPA("glTexCoord2fv"); qglTexCoord2fv = dllTexCoord2fv = (decltype(dllTexCoord2fv))GPA(glTexCoord2fv);
qglTexCoordPointer = dllTexCoordPointer = (decltype(dllTexCoordPointer))GPA("glTexCoordPointer"); qglTexCoordPointer = dllTexCoordPointer = (decltype(dllTexCoordPointer))GPA(glTexCoordPointer);
qglTexEnvf = dllTexEnvf = (decltype(dllTexEnvf))GPA("glTexEnvf"); qglTexEnvf = dllTexEnvf = (decltype(dllTexEnvf))GPA(glTexEnvf);
qglTexImage2D = dllTexImage2D = (decltype(dllTexImage2D))GPA("glTexImage2D"); qglTexImage2D = dllTexImage2D = (decltype(dllTexImage2D))GPA(glTexImage2D);
qglTexParameterf = dllTexParameterf = (decltype(dllTexParameterf))GPA("glTexParameterf"); qglTexParameterf = dllTexParameterf = (decltype(dllTexParameterf))GPA(glTexParameterf);
qglTexParameterfv = dllTexParameterfv = (decltype(dllTexParameterfv))GPA("glTexParameterfv"); qglTexParameterfv = dllTexParameterfv = (decltype(dllTexParameterfv))GPA(glTexParameterfv);
qglTexSubImage2D = dllTexSubImage2D = (decltype(dllTexSubImage2D))GPA("glTexSubImage2D"); qglTexSubImage2D = dllTexSubImage2D = (decltype(dllTexSubImage2D))GPA(glTexSubImage2D);
qglVertex2f = dllVertex2f = (decltype(dllVertex2f))GPA("glVertex2f"); qglVertex2f = dllVertex2f = (decltype(dllVertex2f))GPA(glVertex2f);
qglVertex3f = dllVertex3f = (decltype(dllVertex3f))GPA("glVertex3f"); qglVertex3f = dllVertex3f = (decltype(dllVertex3f))GPA(glVertex3f);
qglVertex3fv = dllVertex3fv = (decltype(dllVertex3fv))GPA("glVertex3fv"); qglVertex3fv = dllVertex3fv = (decltype(dllVertex3fv))GPA(glVertex3fv);
qglVertexPointer = dllVertexPointer = (decltype(dllVertexPointer))GPA("glVertexPointer"); qglVertexPointer = dllVertexPointer = (decltype(dllVertexPointer))GPA(glVertexPointer);
qglViewport = dllViewport = (decltype(dllViewport))GPA("glViewport"); qglViewport = dllViewport = (decltype(dllViewport))GPA(glViewport);
qwglCreateContext = (decltype(qwglCreateContext))GPA("wglCreateContext"); qwglCreateContext = (decltype(qwglCreateContext))GPA(wglCreateContext);
qwglDeleteContext = (decltype(qwglDeleteContext))GPA("wglDeleteContext"); qwglDeleteContext = (decltype(qwglDeleteContext))GPA(wglDeleteContext);
qwglGetProcAddress = (decltype(qwglGetProcAddress))GPA("wglGetProcAddress"); qwglGetProcAddress = (decltype(qwglGetProcAddress))GPA(wglGetProcAddress);
qwglMakeCurrent = (decltype(qwglMakeCurrent))GPA("wglMakeCurrent"); qwglMakeCurrent = (decltype(qwglMakeCurrent))GPA(wglMakeCurrent);
qwglSwapIntervalEXT = 0; qwglSwapIntervalEXT = 0;
qglActiveTextureARB = 0; qglActiveTextureARB = 0;

View File

@ -34,6 +34,12 @@ static float s_flipMatrix[16] = {
0, 0, 0, 1 0, 0, 0, 1
}; };
#ifdef _DEBUG
float fast_sky_color[4] = { 0.8f, 0.7f, 0.4f, 1.0f };
#else
float fast_sky_color[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
#endif
/* /*
** GL_Bind ** GL_Bind
@ -58,7 +64,10 @@ void GL_Bind( image_t *image ) {
qglBindTexture (GL_TEXTURE_2D, texnum); qglBindTexture (GL_TEXTURE_2D, texnum);
// VULKAN // VULKAN
glState.vk_current_images[glState.currenttmu] = final_image; if (vk_active) {
VkDescriptorSet set = vk_resources.images[final_image->index].descriptor_set;
vk_resources.current_descriptor_sets[glState.currenttmu] = set;
}
} }
} }
@ -423,61 +432,17 @@ void RB_BeginDrawingView (void) {
clearBits |= GL_STENCIL_BUFFER_BIT; clearBits |= GL_STENCIL_BUFFER_BIT;
} }
#ifdef _DEBUG
float sky_color[4] = { 0.8f, 0.7f, 0.4f, 1.0f }; // FIXME: get color of sky
#else
float sky_color[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; // FIXME: get color of sky
#endif
bool fast_sky = r_fastsky->integer && !( backEnd.refdef.rdflags & RDF_NOWORLDMODEL ); bool fast_sky = r_fastsky->integer && !( backEnd.refdef.rdflags & RDF_NOWORLDMODEL );
if ( fast_sky ) if ( fast_sky )
{ {
clearBits |= GL_COLOR_BUFFER_BIT; // FIXME: only if sky shaders have been used clearBits |= GL_COLOR_BUFFER_BIT; // FIXME: only if sky shaders have been used
qglClearColor(sky_color[0], sky_color[1], sky_color[2], sky_color[3]); qglClearColor(fast_sky_color[0], fast_sky_color[1], fast_sky_color[2], fast_sky_color[3]);
} }
qglClear( clearBits ); qglClear( clearBits );
// VULKAN // VULKAN
if (glState.vk_dirty_attachments || fast_sky) { vk_clear_attachments(clear_stencil, fast_sky);
VkClearAttachment attachments[2];
uint32_t attachment_count = fast_sky ? 2 : 1;
attachments[0].aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
attachments[0].clearValue.depthStencil.depth = 1.0f;
if (clear_stencil) {
attachments[0].aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
attachments[0].clearValue.depthStencil.stencil = 0;
}
if (fast_sky) {
attachments[1].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
attachments[1].colorAttachment = 0;
attachments[1].clearValue.color = { sky_color[0], sky_color[1], sky_color[2], sky_color[3] };
}
VkClearRect clear_rect[2];
clear_rect[0].rect = vk_get_scissor_rect();
clear_rect[0].baseArrayLayer = 0;
clear_rect[0].layerCount = 1;
int rect_count = 1;
// Split viewport rectangle into two non-overlapping rectangles.
// It's a HACK to prevent Vulkan validation layer's performance warning:
// "vkCmdClearAttachments() issued on command buffer object XXX prior to any Draw Cmds.
// It is recommended you use RenderPass LOAD_OP_CLEAR on Attachments prior to any Draw."
//
if (fast_sky) {
uint32_t h = clear_rect[0].rect.extent.height / 2;
clear_rect[0].rect.extent.height = h;
clear_rect[1] = clear_rect[0];
clear_rect[1].rect.offset.y = h;
rect_count = 2;
}
vkCmdClearAttachments(vk.command_buffer, attachment_count, attachments, rect_count, clear_rect);
}
if ( ( backEnd.refdef.rdflags & RDF_HYPERSPACE ) ) if ( ( backEnd.refdef.rdflags & RDF_HYPERSPACE ) )
{ {
@ -746,12 +711,15 @@ 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
Vk_Image& image = vk_resources.images[tr.scratchImage[client]->index]; if (vk_active) {
vkDestroyImage(vk.device, image.handle, nullptr); Vk_Image& image = vk_resources.images[tr.scratchImage[client]->index];
vkDestroyImageView(vk.device, image.view, nullptr); vkDestroyImage(vk.device, image.handle, nullptr);
vkFreeDescriptorSets(vk.device, vk.descriptor_pool, 1, &image.descriptor_set); vkDestroyImageView(vk.device, image.view, nullptr);
image = vk_create_image(cols, rows, 1, false); vkFreeDescriptorSets(vk.device, vk.descriptor_pool, 1, &image.descriptor_set);
vk_upload_image_data(image.handle, cols, rows, false, data); image = vk_create_image(cols, rows, 1, false);
vk_upload_image_data(image.handle, cols, rows, false, data);
vk_resources.current_descriptor_sets[glState.currenttmu] = image.descriptor_set;
}
} else { } else {
if (dirty) { if (dirty) {
// otherwise, just subimage upload it so that drivers can tell we are going to be changing // otherwise, just subimage upload it so that drivers can tell we are going to be changing
@ -759,8 +727,10 @@ 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
const Vk_Image& image = vk_resources.images[tr.scratchImage[client]->index]; if (vk_active) {
vk_upload_image_data(image.handle, cols, rows, false, data); const Vk_Image& image = vk_resources.images[tr.scratchImage[client]->index];
vk_upload_image_data(image.handle, cols, rows, false, data);
}
} }
} }
} }
@ -900,7 +870,7 @@ const void *RB_DrawBuffer( const void *data ) {
qglDrawBuffer( cmd->buffer ); qglDrawBuffer( cmd->buffer );
// VULKAN // VULKAN
vk_begin_frame(); vk_begin_frame();
return (const void *)(cmd + 1); return (const void *)(cmd + 1);
} }

View File

@ -118,8 +118,7 @@ GL_TextureMode
=============== ===============
*/ */
void GL_TextureMode( const char *string ) { void GL_TextureMode( const char *string ) {
int i; int i;
image_t *glt;
for ( i=0 ; i< 6 ; i++ ) { for ( i=0 ; i< 6 ; i++ ) {
if ( !Q_stricmp( modes[i].name, string ) ) { if ( !Q_stricmp( modes[i].name, string ) ) {
@ -135,22 +134,27 @@ void GL_TextureMode( const char *string ) {
gl_filter_min = modes[i].minimize; gl_filter_min = modes[i].minimize;
gl_filter_max = modes[i].maximize; gl_filter_max = modes[i].maximize;
// VULKAN
VK_CHECK(vkDeviceWaitIdle(vk.device));
// change all the existing mipmap texture objects // change all the existing mipmap texture objects
for ( i = 0 ; i < tr.numImages ; i++ ) { for ( i = 0 ; i < tr.numImages ; i++ ) {
glt = tr.images[ i ]; image_t* glt = tr.images[ i ];
if ( glt->mipmap ) { if ( glt->mipmap ) {
GL_Bind (glt); GL_Bind (glt);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min); qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max); qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
// VULKAN
Vk_Image& image = vk_resources.images[i];
vk_update_descriptor_set(image.descriptor_set, image.view, true, glt->wrapClampMode == GL_REPEAT);
} }
} }
// VULKAN
if (vk_active) {
VK_CHECK(vkDeviceWaitIdle(vk.device));
for ( i = 0 ; i < tr.numImages ; i++ ) {
image_t* glt = tr.images[i];
if (glt->mipmap) {
Vk_Image& image = vk_resources.images[i];
vk_update_descriptor_set(image.descriptor_set, image.view, true, glt->wrapClampMode == GL_REPEAT);
}
}
}
} }
/* /*
@ -718,9 +722,10 @@ static void Upload32( unsigned *data,
done: done:
// VULKAN // VULKAN
image = vk_create_image(*pUploadWidth, *pUploadHeight, miplevel + 1, repeat_texture); if (vk_active) {
vk_upload_image_data(image.handle, *pUploadWidth, *pUploadHeight, mipmap == qtrue, mipmap_buffer); image = vk_create_image(*pUploadWidth, *pUploadHeight, miplevel + 1, repeat_texture);
vk_upload_image_data(image.handle, *pUploadWidth, *pUploadHeight, mipmap == qtrue, mipmap_buffer);
}
if (mipmap_buffer != nullptr) if (mipmap_buffer != nullptr)
ri.Hunk_FreeTempMemory(mipmap_buffer); ri.Hunk_FreeTempMemory(mipmap_buffer);
@ -1880,10 +1885,6 @@ void R_DeleteTextures( void ) {
Com_Memset( glState.currenttextures, 0, sizeof( glState.currenttextures ) ); Com_Memset( glState.currenttextures, 0, sizeof( glState.currenttextures ) );
// VULKAN
vkDeviceWaitIdle(vk.device);
Com_Memset( glState.vk_current_images, 0, sizeof( glState.vk_current_images ) );
if ( qglBindTexture ) { if ( qglBindTexture ) {
GL_SelectTexture( 1 ); GL_SelectTexture( 1 );
qglBindTexture( GL_TEXTURE_2D, 0 ); qglBindTexture( GL_TEXTURE_2D, 0 );

View File

@ -29,6 +29,8 @@ 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 );
@ -989,6 +991,9 @@ void R_Init( void ) {
} }
R_ToggleSmpFrame(); R_ToggleSmpFrame();
gl_active = (r_renderAPI->integer == 0 || r_renderAPICompareWindow->integer > 0);
vk_active = (r_renderAPI->integer > 0 || r_renderAPICompareWindow->integer > 0);
InitOpenGL(); InitOpenGL();
R_InitImages(); R_InitImages();
@ -1027,23 +1032,23 @@ 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();
R_DeleteTextures(); R_DeleteTextures();
// VULKAN
vk_destroy_resources();
} }
R_DoneFreeType(); R_DoneFreeType();
// shut down platform specific OpenGL stuff // shut down platform specific OpenGL stuff
if ( destroyWindow ) { if ( destroyWindow ) {
// VULKAN
vk_destroy_instance();
GLimp_Shutdown(); GLimp_Shutdown();
} }

View File

@ -805,14 +805,6 @@ typedef struct {
int texEnv[2]; int texEnv[2];
int faceCulling; int faceCulling;
unsigned long glStateBits; unsigned long glStateBits;
// VULKAN
// This flag is used to decide whether framebuffer's attachments should be cleared with vmCmdClearAttachment (vk_dirty_attachments == true),
// or they have just been cleared by render pass instance clear op (vk_dirty_attachments == false).
bool vk_dirty_attachments;
image_t* vk_current_images[2];
} glstate_t; } glstate_t;
@ -950,6 +942,8 @@ 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;
// //

View File

@ -362,10 +362,12 @@ static void ProjectDlightTexture( void ) {
backEnd.pc.c_dlightIndexes += numIndexes; backEnd.pc.c_dlightIndexes += numIndexes;
// VULKAN // VULKAN
VkPipeline pipeline = vk.dlight_pipelines[dl->additive > 0 ? 1 : 0][tess.shader->cullType][tess.shader->polygonOffset]; if (vk_active) {
vk_bind_stage_specific_resources(pipeline, false, false); VkPipeline pipeline = vk.dlight_pipelines[dl->additive > 0 ? 1 : 0][tess.shader->cullType][tess.shader->polygonOffset];
vkCmdDrawIndexed(vk.command_buffer, tess.numIndexes, 1, 0, 0, 0); vk_bind_stage_specific_resources(pipeline, false, false);
glState.vk_dirty_attachments = true; vkCmdDrawIndexed(vk.command_buffer, tess.numIndexes, 1, 0, 0, 0);
vk_resources.dirty_attachments = true;
}
} }
} }
@ -406,11 +408,13 @@ static void RB_FogPass( void ) {
R_DrawElements( tess.numIndexes, tess.indexes ); R_DrawElements( tess.numIndexes, tess.indexes );
// VULKAN // VULKAN
assert(tess.shader->fogPass > 0); if (vk_active) {
VkPipeline pipeline = vk.fog_pipelines[tess.shader->fogPass - 1][tess.shader->cullType][tess.shader->polygonOffset]; assert(tess.shader->fogPass > 0);
vk_bind_stage_specific_resources(pipeline, false, false); VkPipeline pipeline = vk.fog_pipelines[tess.shader->fogPass - 1][tess.shader->cullType][tess.shader->polygonOffset];
vkCmdDrawIndexed(vk.command_buffer, tess.numIndexes, 1, 0, 0, 0); vk_bind_stage_specific_resources(pipeline, false, false);
glState.vk_dirty_attachments = true; vkCmdDrawIndexed(vk.command_buffer, tess.numIndexes, 1, 0, 0, 0);
vk_resources.dirty_attachments = true;
}
} }
/* /*
@ -714,10 +718,6 @@ static void ComputeTexCoords( shaderStage_t *pStage ) {
static void RB_IterateStagesGeneric( shaderCommands_t *input ) static void RB_IterateStagesGeneric( shaderCommands_t *input )
{ {
// VULKAN // VULKAN
extern FILE* vk_log_file;
if (r_logFile->integer)
fprintf(vk_log_file, "vk_draw (passes %d, vert %d, inds %d)\n", input->numPasses, tess.numVertexes, tess.numIndexes);
vk_bind_resources_shared_between_stages(); vk_bind_resources_shared_between_stages();
for ( int stage = 0; stage < MAX_SHADER_STAGES; stage++ ) for ( int stage = 0; stage < MAX_SHADER_STAGES; stage++ )
@ -767,15 +767,17 @@ static void RB_IterateStagesGeneric( shaderCommands_t *input )
} }
// VULKAN // VULKAN
VkPipeline pipeline = pStage->vk_pipeline; if (vk_active) {
if (backEnd.viewParms.isMirror) VkPipeline pipeline = pStage->vk_pipeline;
pipeline = pStage->vk_mirror_pipeline; if (backEnd.viewParms.isMirror)
else if (backEnd.viewParms.isPortal) pipeline = pStage->vk_mirror_pipeline;
pipeline = pStage->vk_portal_pipeline; else if (backEnd.viewParms.isPortal)
pipeline = pStage->vk_portal_pipeline;
vk_bind_stage_specific_resources(pipeline, multitexture, input->shader->isSky == qtrue); vk_bind_stage_specific_resources(pipeline, multitexture, input->shader->isSky == qtrue);
vkCmdDrawIndexed(vk.command_buffer, tess.numIndexes, 1, 0, 0, 0); vkCmdDrawIndexed(vk.command_buffer, tess.numIndexes, 1, 0, 0, 0);
glState.vk_dirty_attachments = true; vk_resources.dirty_attachments = true;
}
// allow skipping out to show just lightmaps during development // allow skipping out to show just lightmaps during development
if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap ) ) if ( r_lightmap->integer && ( pStage->bundle[0].isLightmap || pStage->bundle[1].isLightmap ) )

View File

@ -2160,35 +2160,37 @@ static shader_t *FinishShader( void ) {
shader.sort = SS_FOG; shader.sort = SS_FOG;
} }
// VULKAN // VULKAN: create pipelines for each shader stage
Vk_Pipeline_Def def; if (vk_active) {
def.face_culling = shader.cullType; Vk_Pipeline_Def def;
def.polygon_offset = (shader.polygonOffset == qtrue); def.face_culling = shader.cullType;
def.polygon_offset = (shader.polygonOffset == qtrue);
for (int i = 0; i < stage; i++) { for (int i = 0; i < stage; i++) {
shaderStage_t *pStage = &stages[i]; shaderStage_t *pStage = &stages[i];
def.state_bits = pStage->stateBits; def.state_bits = pStage->stateBits;
if (pStage->bundle[1].image[0] == nullptr) if (pStage->bundle[1].image[0] == nullptr)
def.shader_type = Vk_Shader_Type::single_texture; def.shader_type = Vk_Shader_Type::single_texture;
else if (shader.multitextureEnv == GL_MODULATE) else if (shader.multitextureEnv == GL_MODULATE)
def.shader_type = Vk_Shader_Type::multi_texture_mul; def.shader_type = Vk_Shader_Type::multi_texture_mul;
else if (shader.multitextureEnv == GL_ADD) else if (shader.multitextureEnv == GL_ADD)
def.shader_type = Vk_Shader_Type::multi_texture_add; def.shader_type = Vk_Shader_Type::multi_texture_add;
else else
ri.Error(ERR_DROP, "ERROR: could not determine vulkan shader type for shader '%s'\n", shader.name); ri.Error(ERR_FATAL, "Vulkan: could not create pipelines for q3 shader '%s'\n", shader.name);
def.clipping_plane = false; def.clipping_plane = false;
def.mirror = false; def.mirror = false;
pStage->vk_pipeline = vk_find_pipeline(def); pStage->vk_pipeline = vk_find_pipeline(def);
def.clipping_plane = true; def.clipping_plane = true;
def.mirror = false; def.mirror = false;
pStage->vk_portal_pipeline = vk_find_pipeline(def); pStage->vk_portal_pipeline = vk_find_pipeline(def);
def.clipping_plane = true; def.clipping_plane = true;
def.mirror = true; def.mirror = true;
pStage->vk_mirror_pipeline = vk_find_pipeline(def); pStage->vk_mirror_pipeline = vk_find_pipeline(def);
}
} }
return GeneratePermanentShader(); return GeneratePermanentShader();

View File

@ -450,52 +450,56 @@ static void DrawSkyBox( shader_t *shader )
sky_mins_subd, sky_mins_subd,
sky_maxs_subd ); sky_maxs_subd );
// VULKAN // VULKAN: draw skybox side
glState.vk_current_images[0] = shader->sky.outerbox[sky_texorder[i]]; if (vk_active) {
tess.numVertexes = 0; VkDescriptorSet set = vk_resources.images[shader->sky.outerbox[sky_texorder[i]]->index].descriptor_set;
tess.numIndexes = 0; vk_resources.current_descriptor_sets[0] = set;
for ( t = sky_mins_subd[1]+HALF_SKY_SUBDIVISIONS; t < sky_maxs_subd[1]+HALF_SKY_SUBDIVISIONS; t++ ) tess.numVertexes = 0;
{ tess.numIndexes = 0;
for ( s = sky_mins_subd[0]+HALF_SKY_SUBDIVISIONS; s < sky_maxs_subd[0]+HALF_SKY_SUBDIVISIONS; s++ )
for ( t = sky_mins_subd[1]+HALF_SKY_SUBDIVISIONS; t < sky_maxs_subd[1]+HALF_SKY_SUBDIVISIONS; t++ )
{ {
int ndx = tess.numVertexes; for ( s = sky_mins_subd[0]+HALF_SKY_SUBDIVISIONS; s < sky_maxs_subd[0]+HALF_SKY_SUBDIVISIONS; s++ )
{
int ndx = tess.numVertexes;
tess.indexes[ tess.numIndexes ] = ndx; tess.indexes[ tess.numIndexes ] = ndx;
tess.indexes[ tess.numIndexes + 1 ] = ndx + 1; tess.indexes[ tess.numIndexes + 1 ] = ndx + 1;
tess.indexes[ tess.numIndexes + 2 ] = ndx + 2; tess.indexes[ tess.numIndexes + 2 ] = ndx + 2;
tess.indexes[ tess.numIndexes + 3 ] = ndx + 2; tess.indexes[ tess.numIndexes + 3 ] = ndx + 2;
tess.indexes[ tess.numIndexes + 4 ] = ndx + 1; tess.indexes[ tess.numIndexes + 4 ] = ndx + 1;
tess.indexes[ tess.numIndexes + 5 ] = ndx + 3; tess.indexes[ tess.numIndexes + 5 ] = ndx + 3;
tess.numIndexes += 6; tess.numIndexes += 6;
VectorCopy(s_skyPoints[t][s], tess.xyz[ndx]); VectorCopy(s_skyPoints[t][s], tess.xyz[ndx]);
tess.svars.texcoords[0][ndx][0] = s_skyTexCoords[t][s][0]; tess.svars.texcoords[0][ndx][0] = s_skyTexCoords[t][s][0];
tess.svars.texcoords[0][ndx][1] = s_skyTexCoords[t][s][1]; tess.svars.texcoords[0][ndx][1] = s_skyTexCoords[t][s][1];
VectorCopy(s_skyPoints[t + 1][s], tess.xyz[ndx + 1]); VectorCopy(s_skyPoints[t + 1][s], tess.xyz[ndx + 1]);
tess.svars.texcoords[0][ndx + 1][0] = s_skyTexCoords[t + 1][s][0]; tess.svars.texcoords[0][ndx + 1][0] = s_skyTexCoords[t + 1][s][0];
tess.svars.texcoords[0][ndx + 1][1] = s_skyTexCoords[t + 1][s][1]; tess.svars.texcoords[0][ndx + 1][1] = s_skyTexCoords[t + 1][s][1];
VectorCopy(s_skyPoints[t][s + 1], tess.xyz[ndx + 2]); VectorCopy(s_skyPoints[t][s + 1], tess.xyz[ndx + 2]);
tess.svars.texcoords[0][ndx + 2][0] = s_skyTexCoords[t][s + 1][0]; tess.svars.texcoords[0][ndx + 2][0] = s_skyTexCoords[t][s + 1][0];
tess.svars.texcoords[0][ndx + 2][1] = s_skyTexCoords[t][s + 1][1]; tess.svars.texcoords[0][ndx + 2][1] = s_skyTexCoords[t][s + 1][1];
VectorCopy(s_skyPoints[t + 1][s + 1], tess.xyz[ndx + 3]); VectorCopy(s_skyPoints[t + 1][s + 1], tess.xyz[ndx + 3]);
tess.svars.texcoords[0][ndx + 3][0] = s_skyTexCoords[t + 1][s + 1][0]; tess.svars.texcoords[0][ndx + 3][0] = s_skyTexCoords[t + 1][s + 1][0];
tess.svars.texcoords[0][ndx + 3][1] = s_skyTexCoords[t + 1][s + 1][1]; tess.svars.texcoords[0][ndx + 3][1] = s_skyTexCoords[t + 1][s + 1][1];
tess.numVertexes += 4; tess.numVertexes += 4;
}
} }
}
Com_Memset( tess.svars.colors, tr.identityLightByte, tess.numVertexes * 4 ); Com_Memset( tess.svars.colors, tr.identityLightByte, tess.numVertexes * 4 );
vk_bind_resources_shared_between_stages(); vk_bind_resources_shared_between_stages();
vk_bind_stage_specific_resources(vk.skybox_pipeline, false, true); vk_bind_stage_specific_resources(vk.skybox_pipeline, false, true);
vkCmdDrawIndexed(vk.command_buffer, tess.numIndexes, 1, 0, 0, 0); vkCmdDrawIndexed(vk.command_buffer, tess.numIndexes, 1, 0, 0, 0);
glState.vk_dirty_attachments = true; vk_resources.dirty_attachments = true;
vk.xyz_elements += tess.numVertexes; vk.xyz_elements += tess.numVertexes;
}
} }
} }

View File

@ -7,6 +7,8 @@
FILE* vk_log_file; FILE* vk_log_file;
extern float fast_sky_color[4];
const int VERTEX_CHUNK_SIZE = 512 * 1024; const int VERTEX_CHUNK_SIZE = 512 * 1024;
const int XYZ_SIZE = 4 * VERTEX_CHUNK_SIZE; const int XYZ_SIZE = 4 * VERTEX_CHUNK_SIZE;
@ -1617,6 +1619,51 @@ VkPipeline vk_find_pipeline(const Vk_Pipeline_Def& def) {
return pipeline; return pipeline;
} }
void vk_clear_attachments(bool clear_stencil, bool fast_sky) {
if (!vk_active)
return;
if (!vk_resources.dirty_attachments && !fast_sky)
return;
VkClearAttachment attachments[2];
uint32_t attachment_count = fast_sky ? 2 : 1;
attachments[0].aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
attachments[0].clearValue.depthStencil.depth = 1.0f;
if (clear_stencil) {
attachments[0].aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
attachments[0].clearValue.depthStencil.stencil = 0;
}
if (fast_sky) {
attachments[1].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
attachments[1].colorAttachment = 0;
attachments[1].clearValue.color = { fast_sky_color[0], fast_sky_color[1], fast_sky_color[2], fast_sky_color[3] };
}
VkClearRect clear_rect[2];
clear_rect[0].rect = vk_get_scissor_rect();
clear_rect[0].baseArrayLayer = 0;
clear_rect[0].layerCount = 1;
int rect_count = 1;
// Split viewport rectangle into two non-overlapping rectangles.
// It's a HACK to prevent Vulkan validation layer's performance warning:
// "vkCmdClearAttachments() issued on command buffer object XXX prior to any Draw Cmds.
// It is recommended you use RenderPass LOAD_OP_CLEAR on Attachments prior to any Draw."
//
if (fast_sky) {
uint32_t h = clear_rect[0].rect.extent.height / 2;
clear_rect[0].rect.extent.height = h;
clear_rect[1] = clear_rect[0];
clear_rect[1].rect.offset.y = h;
rect_count = 2;
}
vkCmdClearAttachments(vk.command_buffer, attachment_count, attachments, rect_count, clear_rect);
}
static VkRect2D get_viewport_rect() { static VkRect2D get_viewport_rect() {
VkRect2D r; VkRect2D r;
if (backEnd.projection2D) { if (backEnd.projection2D) {
@ -1708,6 +1755,8 @@ 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;
// xyz // xyz
{ {
if ((vk.xyz_elements + tess.numVertexes) * sizeof(vec4_t) > XYZ_SIZE) if ((vk.xyz_elements + tess.numVertexes) * sizeof(vec4_t) > XYZ_SIZE)
@ -1821,12 +1870,7 @@ void vk_bind_stage_specific_resources(VkPipeline pipeline, bool multitexture, bo
// bind descriptor sets // bind descriptor sets
uint32_t set_count = multitexture ? 2 : 1; uint32_t set_count = multitexture ? 2 : 1;
VkDescriptorSet sets[2]; vkCmdBindDescriptorSets(vk.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vk.pipeline_layout, 0, set_count, vk_resources.current_descriptor_sets, 0, nullptr);
sets[0] = vk_resources.images[glState.vk_current_images[0]->index].descriptor_set;
if (multitexture) {
sets[1] = vk_resources.images[glState.vk_current_images[1]->index].descriptor_set;
}
vkCmdBindDescriptorSets(vk.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, vk.pipeline_layout, 0, set_count, sets, 0, nullptr);
// bind pipeline // bind pipeline
vkCmdBindPipeline(vk.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); vkCmdBindPipeline(vk.command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
@ -1844,6 +1888,9 @@ void vk_bind_stage_specific_resources(VkPipeline pipeline, bool multitexture, bo
} }
void vk_begin_frame() { void vk_begin_frame() {
if (!vk_active)
return;
if (r_logFile->integer) if (r_logFile->integer)
fprintf(vk_log_file, "vk_begin_frame\n"); fprintf(vk_log_file, "vk_begin_frame\n");
@ -1876,15 +1923,17 @@ void vk_begin_frame() {
render_pass_begin_info.pClearValues = clear_values; render_pass_begin_info.pClearValues = clear_values;
vkCmdBeginRenderPass(vk.command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE); vkCmdBeginRenderPass(vk.command_buffer, &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE);
vk_resources.dirty_attachments = false;
vk.xyz_elements = 0; vk.xyz_elements = 0;
vk.color_st_elements = 0; vk.color_st_elements = 0;
vk.index_buffer_offset = 0; vk.index_buffer_offset = 0;
glState.vk_dirty_attachments = false;
} }
void vk_end_frame() { void vk_end_frame() {
if (!vk_active)
return;
if (r_logFile->integer) if (r_logFile->integer)
fprintf(vk_log_file, "end_frame (vb_size %d, ib_size %d)\n", fprintf(vk_log_file, "end_frame (vb_size %d, ib_size %d)\n",
vk.xyz_elements * 16 + vk.color_st_elements * 20, vk.xyz_elements * 16 + vk.color_st_elements * 20,

View File

@ -71,6 +71,7 @@ VkPipeline vk_find_pipeline(const Vk_Pipeline_Def& def);
// Rendering setup. // Rendering setup.
// //
VkRect2D vk_get_scissor_rect(); VkRect2D vk_get_scissor_rect();
void vk_clear_attachments(bool clear_stencil, bool fast_sky);
void vk_bind_resources_shared_between_stages(); void vk_bind_resources_shared_between_stages();
void vk_bind_stage_specific_resources(VkPipeline pipeline, bool multitexture, bool sky); void vk_bind_stage_specific_resources(VkPipeline pipeline, bool multitexture, bool sky);
void vk_begin_frame(); void vk_begin_frame();
@ -175,4 +176,16 @@ struct Vk_Resources {
VkDeviceMemory staging_buffer_memory = VK_NULL_HANDLE; VkDeviceMemory staging_buffer_memory = VK_NULL_HANDLE;
VkDeviceSize staging_buffer_size = 0; VkDeviceSize staging_buffer_size = 0;
byte* staging_buffer_ptr = nullptr; // pointer to mapped staging buffer byte* staging_buffer_ptr = nullptr; // pointer to mapped staging buffer
//
// State.
//
// Descriptor sets corresponding to bound texture images.
VkDescriptorSet current_descriptor_sets[2];
// This flag is used to decide whether framebuffer's attachments should be cleared
// with vmCmdClearAttachment (dirty_attachments == true), or they have just been
// cleared by render pass instance clear op (dirty_attachments == false).
bool dirty_attachments;
}; };