searching for valid sample counts for MSAA in GL2 and GL3 instead of failing

This commit is contained in:
myT 2019-12-26 16:24:22 +01:00
parent a89a2e3ead
commit 9cb02a32bf
4 changed files with 88 additions and 63 deletions

View file

@ -83,6 +83,8 @@ add: r_mapBrightness now works on q3map2's external lightmap atlas images
add: the renderer can now batch surfaces with different (but sufficiently similar) shaders add: the renderer can now batch surfaces with different (but sufficiently similar) shaders
this new optimization works with the output of "Frozen Sand Particle Studio" this new optimization works with the output of "Frozen Sand Particle Studio"
chg: searching for valid sample counts for MSAA in GL2 and GL3 instead of failing right away
add: /modellist /skinlist /imagelist /shaderlist can now filter results with pattern matching add: /modellist /skinlist /imagelist /shaderlist can now filter results with pattern matching
chg: SSE2 instruction set support is now required chg: SSE2 instruction set support is now required

View file

@ -51,6 +51,9 @@ static void RB_FogPass();
static void GAL_Begin2D(); static void GAL_Begin2D();
static GLint GetTexEnv( texEnv_t texEnv ); static GLint GetTexEnv( texEnv_t texEnv );
void GL_GetRenderTargetFormat( GLenum* internalFormat, GLenum* format, GLenum* type, int cnq3Format );
void GL_CreateColorRenderBufferStorageMS( int* samples );
struct GLSL_Program { struct GLSL_Program {
GLuint p; // linked program GLuint p; // linked program
@ -334,12 +337,12 @@ static unsigned int frameBufferReadIndex = 0; // read this for the latest color/
static qbool frameBufferMultiSampling = qfalse; static qbool frameBufferMultiSampling = qfalse;
#define CASE( x ) case x: return #x
#define GL( call ) call; GL2_CheckError( #call, __FUNCTION__, __FILE__, __LINE__ ) #define GL( call ) call; GL2_CheckError( #call, __FUNCTION__, __FILE__, __LINE__ )
static const char* GL2_GetErrorString( GLenum ec ) static const char* GL2_GetErrorString( GLenum ec )
{ {
#define CASE( x ) case x: return #x
switch ( ec ) switch ( ec )
{ {
CASE( GL_NO_ERROR ); CASE( GL_NO_ERROR );
@ -352,6 +355,7 @@ static const char* GL2_GetErrorString( GLenum ec )
CASE( GL_STACK_OVERFLOW ); CASE( GL_STACK_OVERFLOW );
default: return "?"; default: return "?";
} }
#undef CASE
} }
@ -377,53 +381,6 @@ static void GL2_CheckError( const char* call, const char* function, const char*
} }
static const char* GL2_GetFBOStatusString( GLenum status )
{
switch ( status )
{
CASE( GL_FRAMEBUFFER_COMPLETE );
CASE( GL_FRAMEBUFFER_UNDEFINED );
CASE( GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT );
CASE( GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT );
CASE( GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER );
CASE( GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER );
CASE( GL_FRAMEBUFFER_UNSUPPORTED );
CASE( GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE );
CASE( GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS );
default: return "?";
}
}
#undef CASE
void GL_GetRenderTargetFormat( GLenum* internalFormat, GLenum* format, GLenum* type, int cnq3Format )
{
switch( cnq3Format )
{
case RTCF_R10G10B10A2:
*internalFormat = GL_RGB10_A2;
*format = GL_BGRA;
*type = GL_UNSIGNED_INT_2_10_10_10_REV;
break;
case RTCF_R16G16B16A16:
*internalFormat = GL_RGBA16;
*format = GL_BGRA;
*type = GL_UNSIGNED_SHORT;
break;
case RTCF_R8G8B8A8:
default:
*internalFormat = GL_RGBA8;
*format = GL_BGRA;
*type = GL_UNSIGNED_BYTE;
break;
}
}
static qbool GL2_FBO_CreateSS( FrameBuffer& fb, qbool depthStencil ) static qbool GL2_FBO_CreateSS( FrameBuffer& fb, qbool depthStencil )
{ {
while ( glGetError() != GL_NO_ERROR ) {} // clear the error queue while ( glGetError() != GL_NO_ERROR ) {} // clear the error queue
@ -454,8 +411,7 @@ static qbool GL2_FBO_CreateSS( FrameBuffer& fb, qbool depthStencil )
const GLenum fboStatus = glCheckFramebufferStatus( GL_FRAMEBUFFER ); const GLenum fboStatus = glCheckFramebufferStatus( GL_FRAMEBUFFER );
if ( fboStatus != GL_FRAMEBUFFER_COMPLETE ) if ( fboStatus != GL_FRAMEBUFFER_COMPLETE )
{ {
ri.Printf( PRINT_ERROR, "Failed to create FBO (status 0x%X, error 0x%X)\n", (unsigned int)fboStatus, (unsigned int)glGetError() ); ri.Error( ERR_FATAL, "Failed to create FBO (status 0x%X, error 0x%X)\n", (unsigned int)fboStatus, (unsigned int)glGetError() );
ri.Printf( PRINT_ERROR, "FBO status string: %s\n", GL2_GetFBOStatusString(fboStatus) );
return qfalse; return qfalse;
} }
@ -474,16 +430,15 @@ static qbool GL2_FBO_CreateMS( FrameBuffer& fb )
GL(glGenFramebuffers( 1, &fb.fbo )); GL(glGenFramebuffers( 1, &fb.fbo ));
GL(glBindFramebuffer( GL_FRAMEBUFFER, fb.fbo )); GL(glBindFramebuffer( GL_FRAMEBUFFER, fb.fbo ));
GLenum internalFormat, format, type; int sampleCount = 0;
GL_GetRenderTargetFormat( &internalFormat, &format, &type, r_rtColorFormat->integer );
GL(glGenRenderbuffers( 1, &fb.color )); GL(glGenRenderbuffers( 1, &fb.color ));
GL(glBindRenderbuffer( GL_RENDERBUFFER, fb.color )); GL(glBindRenderbuffer( GL_RENDERBUFFER, fb.color ));
GL(glRenderbufferStorageMultisample( GL_RENDERBUFFER, r_msaa->integer, internalFormat, glConfig.vidWidth, glConfig.vidHeight )); GL_CreateColorRenderBufferStorageMS( &sampleCount );
GL(glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fb.color )); GL(glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fb.color ));
GL(glGenRenderbuffers( 1, &fb.depthStencil )); GL(glGenRenderbuffers( 1, &fb.depthStencil ));
GL(glBindRenderbuffer( GL_RENDERBUFFER, fb.depthStencil )); GL(glBindRenderbuffer( GL_RENDERBUFFER, fb.depthStencil ));
GL(glRenderbufferStorageMultisample( GL_RENDERBUFFER, r_msaa->integer, GL_DEPTH24_STENCIL8, glConfig.vidWidth, glConfig.vidHeight )); GL(glRenderbufferStorageMultisample( GL_RENDERBUFFER, sampleCount, GL_DEPTH24_STENCIL8, glConfig.vidWidth, glConfig.vidHeight ));
GL(glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fb.color )); GL(glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fb.color ));
GL(glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb.depthStencil )); GL(glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb.depthStencil ));
@ -491,8 +446,7 @@ static qbool GL2_FBO_CreateMS( FrameBuffer& fb )
const GLenum fboStatus = glCheckFramebufferStatus( GL_FRAMEBUFFER ); const GLenum fboStatus = glCheckFramebufferStatus( GL_FRAMEBUFFER );
if ( fboStatus != GL_FRAMEBUFFER_COMPLETE ) if ( fboStatus != GL_FRAMEBUFFER_COMPLETE )
{ {
ri.Printf( PRINT_ERROR, "Failed to create FBO (status 0x%X, error 0x%X)\n", (unsigned int)fboStatus, (unsigned int)glGetError() ); ri.Error( ERR_FATAL, "Failed to create FBO (status 0x%X, error 0x%X)\n", (unsigned int)fboStatus, (unsigned int)glGetError() );
ri.Printf( PRINT_ERROR, "FBO status string: %s\n", GL2_GetFBOStatusString(fboStatus) );
return qfalse; return qfalse;
} }
@ -500,6 +454,8 @@ static qbool GL2_FBO_CreateMS( FrameBuffer& fb )
fb.multiSampled = qtrue; fb.multiSampled = qtrue;
fb.hasDepthStencil = qtrue; fb.hasDepthStencil = qtrue;
ri.Printf( PRINT_ALL, "MSAA: %d samples requested, %d selected\n", r_msaa->integer, sampleCount );
return qtrue; return qtrue;
} }
@ -507,7 +463,7 @@ static qbool GL2_FBO_CreateMS( FrameBuffer& fb )
static qbool GL2_FBO_Init() static qbool GL2_FBO_Init()
{ {
const int msaa = r_msaa->integer; const int msaa = r_msaa->integer;
const qbool enable = msaa >= 2 && msaa <= 16; const qbool enable = msaa >= 2;
frameBufferMultiSampling = enable; frameBufferMultiSampling = enable;
if ( !enable ) if ( !enable )

View file

@ -650,6 +650,72 @@ static const char* downSample_cs =
" imageStore(dstTex, dstTC, r);\n" " imageStore(dstTex, dstTC, r);\n"
"}\n"; "}\n";
void GL_GetRenderTargetFormat(GLenum* internalFormat, GLenum* format, GLenum* type, int cnq3Format)
{
switch(cnq3Format)
{
case RTCF_R10G10B10A2:
*internalFormat = GL_RGB10_A2;
*format = GL_BGRA;
*type = GL_UNSIGNED_INT_2_10_10_10_REV;
break;
case RTCF_R16G16B16A16:
*internalFormat = GL_RGBA16;
*format = GL_BGRA;
*type = GL_UNSIGNED_SHORT;
break;
case RTCF_R8G8B8A8:
default:
*internalFormat = GL_RGBA8;
*format = GL_BGRA;
*type = GL_UNSIGNED_BYTE;
break;
}
}
void GL_CreateColorRenderBufferStorageMS(int* samples)
{
GLenum internalFormat, format, type;
GL_GetRenderTargetFormat(&internalFormat, &format, &type, r_rtColorFormat->integer);
int sampleCount = r_msaa->integer;
while(glGetError() != GL_NO_ERROR) {} // clear the error queue
if(GLEW_VERSION_4_2 || GLEW_ARB_internalformat_query)
{
GLint maxSampleCount = 0;
glGetInternalformativ(GL_RENDERBUFFER, internalFormat, GL_SAMPLES, 1, &maxSampleCount);
if(glGetError() == GL_NO_ERROR)
{
sampleCount = min(sampleCount, (int)maxSampleCount);
}
}
GLenum errorCode = GL_NO_ERROR;
for(;;)
{
// @NOTE: when the sample count is invalid, the error code is GL_INVALID_OPERATION
glRenderbufferStorageMultisample(GL_RENDERBUFFER, sampleCount, internalFormat, glConfig.vidWidth, glConfig.vidHeight);
errorCode = glGetError();
if(errorCode == GL_NO_ERROR || sampleCount == 0)
{
break;
}
--sampleCount;
}
if(errorCode != GL_NO_ERROR)
{
ri.Error(ERR_FATAL, "Failed to create multi-sampled render buffer storage (error 0x%X)\n", (unsigned int)errorCode);
}
*samples = sampleCount;
}
#if defined(_WIN32) #if defined(_WIN32)
static void AllocatePinnedMemory(ArrayBuffer* buffer) static void AllocatePinnedMemory(ArrayBuffer* buffer)
@ -879,17 +945,16 @@ static void FBO_CreateMS(FrameBuffer* fb, const char* name)
glGenFramebuffers(1, &fb->fbo); glGenFramebuffers(1, &fb->fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fb->fbo); glBindFramebuffer(GL_FRAMEBUFFER, fb->fbo);
GLenum internalFormat, format, type; int sampleCount = 0;
GL_GetRenderTargetFormat(&internalFormat, &format, &type, r_rtColorFormat->integer);
glGenRenderbuffers(1, &fb->color); glGenRenderbuffers(1, &fb->color);
glBindRenderbuffer(GL_RENDERBUFFER, fb->color); glBindRenderbuffer(GL_RENDERBUFFER, fb->color);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, r_msaa->integer, internalFormat, glConfig.vidWidth, glConfig.vidHeight); GL_CreateColorRenderBufferStorageMS(&sampleCount);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fb->color); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fb->color);
SetDebugName(GL_RENDERBUFFER, fb->color, va("%s color attachment 0", name)); SetDebugName(GL_RENDERBUFFER, fb->color, va("%s color attachment 0", name));
glGenRenderbuffers(1, &fb->depthStencil); glGenRenderbuffers(1, &fb->depthStencil);
glBindRenderbuffer(GL_RENDERBUFFER, fb->depthStencil); glBindRenderbuffer(GL_RENDERBUFFER, fb->depthStencil);
glRenderbufferStorageMultisample(GL_RENDERBUFFER, r_msaa->integer, GL_DEPTH24_STENCIL8, glConfig.vidWidth, glConfig.vidHeight); glRenderbufferStorageMultisample(GL_RENDERBUFFER, sampleCount, GL_DEPTH24_STENCIL8, glConfig.vidWidth, glConfig.vidHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->depthStencil); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb->depthStencil);
SetDebugName(GL_RENDERBUFFER, fb->depthStencil, va("%s depth/stencil attachment", name)); SetDebugName(GL_RENDERBUFFER, fb->depthStencil, va("%s depth/stencil attachment", name));
@ -905,12 +970,14 @@ static void FBO_CreateMS(FrameBuffer* fb, const char* name)
fb->multiSampled = qtrue; fb->multiSampled = qtrue;
fb->hasDepthStencil = qtrue; fb->hasDepthStencil = qtrue;
fb->hasColor = qtrue; fb->hasColor = qtrue;
ri.Printf(PRINT_ALL, "MSAA: %d samples requested, %d selected\n", r_msaa->integer, sampleCount);
} }
static void FBO_Init() static void FBO_Init()
{ {
const int msaa = r_msaa->integer; const int msaa = r_msaa->integer;
gl.fbMSEnabled = msaa >= 2 && msaa <= 16; gl.fbMSEnabled = msaa >= 2;
if(gl.fbMSEnabled) if(gl.fbMSEnabled)
{ {

View file

@ -367,7 +367,7 @@ static const cvarTableItem_t r_cvars[] =
{ &r_d3d11_syncOffsets, "r_d3d11_syncOffsets", "2", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "0", XSTRING(D3D11SO_MAX), help_r_d3d11_syncOffsets }, { &r_d3d11_syncOffsets, "r_d3d11_syncOffsets", "2", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "0", XSTRING(D3D11SO_MAX), help_r_d3d11_syncOffsets },
{ &r_d3d11_maxQueuedFrames, "r_d3d11_maxQueuedFrames", "3", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "1", "16", help_r_d3d11_maxQueuedFrames }, { &r_d3d11_maxQueuedFrames, "r_d3d11_maxQueuedFrames", "3", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "1", "16", help_r_d3d11_maxQueuedFrames },
{ &r_ext_max_anisotropy, "r_ext_max_anisotropy", "16", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "0", "16", help_r_ext_max_anisotropy }, { &r_ext_max_anisotropy, "r_ext_max_anisotropy", "16", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "0", "16", help_r_ext_max_anisotropy },
{ &r_msaa, "r_msaa", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "0", "16", "anti-aliasing sample count, " S_COLOR_VAL "0" S_COLOR_HELP "=off" }, { &r_msaa, "r_msaa", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "0", "32", "anti-aliasing sample count, " S_COLOR_VAL "0" S_COLOR_HELP "=off" },
{ &r_picmip, "r_picmip", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "0", "16", help_r_picmip }, { &r_picmip, "r_picmip", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_INTEGER, "0", "16", help_r_picmip },
{ &r_roundImagesDown, "r_roundImagesDown", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, help_r_roundImagesDown }, { &r_roundImagesDown, "r_roundImagesDown", "0", CVAR_ARCHIVE | CVAR_LATCH, CVART_BOOL, NULL, NULL, help_r_roundImagesDown },
{ &r_colorMipLevels, "r_colorMipLevels", "0", CVAR_LATCH, CVART_BOOL, NULL, NULL, "colorizes textures based on their mip level" }, { &r_colorMipLevels, "r_colorMipLevels", "0", CVAR_LATCH, CVART_BOOL, NULL, NULL, "colorizes textures based on their mip level" },