mirror of
https://bitbucket.org/CPMADevs/cnq3
synced 2024-11-10 06:31:48 +00:00
searching for valid sample counts for MSAA in GL2 and GL3 instead of failing
This commit is contained in:
parent
a89a2e3ead
commit
9cb02a32bf
4 changed files with 88 additions and 63 deletions
|
@ -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
|
||||
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
|
||||
|
||||
chg: SSE2 instruction set support is now required
|
||||
|
|
|
@ -51,6 +51,9 @@ static void RB_FogPass();
|
|||
static void GAL_Begin2D();
|
||||
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 {
|
||||
GLuint p; // linked program
|
||||
|
@ -334,12 +337,12 @@ static unsigned int frameBufferReadIndex = 0; // read this for the latest color/
|
|||
static qbool frameBufferMultiSampling = qfalse;
|
||||
|
||||
|
||||
#define CASE( x ) case x: return #x
|
||||
#define GL( call ) call; GL2_CheckError( #call, __FUNCTION__, __FILE__, __LINE__ )
|
||||
|
||||
|
||||
static const char* GL2_GetErrorString( GLenum ec )
|
||||
{
|
||||
#define CASE( x ) case x: return #x
|
||||
switch ( ec )
|
||||
{
|
||||
CASE( GL_NO_ERROR );
|
||||
|
@ -352,6 +355,7 @@ static const char* GL2_GetErrorString( GLenum ec )
|
|||
CASE( GL_STACK_OVERFLOW );
|
||||
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 )
|
||||
{
|
||||
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 );
|
||||
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.Printf( PRINT_ERROR, "FBO status string: %s\n", GL2_GetFBOStatusString(fboStatus) );
|
||||
ri.Error( ERR_FATAL, "Failed to create FBO (status 0x%X, error 0x%X)\n", (unsigned int)fboStatus, (unsigned int)glGetError() );
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
|
@ -474,16 +430,15 @@ static qbool GL2_FBO_CreateMS( FrameBuffer& fb )
|
|||
GL(glGenFramebuffers( 1, &fb.fbo ));
|
||||
GL(glBindFramebuffer( GL_FRAMEBUFFER, fb.fbo ));
|
||||
|
||||
GLenum internalFormat, format, type;
|
||||
GL_GetRenderTargetFormat( &internalFormat, &format, &type, r_rtColorFormat->integer );
|
||||
int sampleCount = 0;
|
||||
GL(glGenRenderbuffers( 1, &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(glGenRenderbuffers( 1, &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_STENCIL_ATTACHMENT, GL_RENDERBUFFER, fb.depthStencil ));
|
||||
|
@ -491,8 +446,7 @@ static qbool GL2_FBO_CreateMS( FrameBuffer& fb )
|
|||
const GLenum fboStatus = glCheckFramebufferStatus( GL_FRAMEBUFFER );
|
||||
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.Printf( PRINT_ERROR, "FBO status string: %s\n", GL2_GetFBOStatusString(fboStatus) );
|
||||
ri.Error( ERR_FATAL, "Failed to create FBO (status 0x%X, error 0x%X)\n", (unsigned int)fboStatus, (unsigned int)glGetError() );
|
||||
return qfalse;
|
||||
}
|
||||
|
||||
|
@ -500,6 +454,8 @@ static qbool GL2_FBO_CreateMS( FrameBuffer& fb )
|
|||
fb.multiSampled = qtrue;
|
||||
fb.hasDepthStencil = qtrue;
|
||||
|
||||
ri.Printf( PRINT_ALL, "MSAA: %d samples requested, %d selected\n", r_msaa->integer, sampleCount );
|
||||
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
|
@ -507,7 +463,7 @@ static qbool GL2_FBO_CreateMS( FrameBuffer& fb )
|
|||
static qbool GL2_FBO_Init()
|
||||
{
|
||||
const int msaa = r_msaa->integer;
|
||||
const qbool enable = msaa >= 2 && msaa <= 16;
|
||||
const qbool enable = msaa >= 2;
|
||||
frameBufferMultiSampling = enable;
|
||||
|
||||
if ( !enable )
|
||||
|
|
|
@ -650,6 +650,72 @@ static const char* downSample_cs =
|
|||
" imageStore(dstTex, dstTC, r);\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)
|
||||
|
||||
static void AllocatePinnedMemory(ArrayBuffer* buffer)
|
||||
|
@ -879,17 +945,16 @@ static void FBO_CreateMS(FrameBuffer* fb, const char* name)
|
|||
glGenFramebuffers(1, &fb->fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb->fbo);
|
||||
|
||||
GLenum internalFormat, format, type;
|
||||
GL_GetRenderTargetFormat(&internalFormat, &format, &type, r_rtColorFormat->integer);
|
||||
int sampleCount = 0;
|
||||
glGenRenderbuffers(1, &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);
|
||||
SetDebugName(GL_RENDERBUFFER, fb->color, va("%s color attachment 0", name));
|
||||
|
||||
glGenRenderbuffers(1, &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);
|
||||
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->hasDepthStencil = qtrue;
|
||||
fb->hasColor = qtrue;
|
||||
|
||||
ri.Printf(PRINT_ALL, "MSAA: %d samples requested, %d selected\n", r_msaa->integer, sampleCount);
|
||||
}
|
||||
|
||||
static void FBO_Init()
|
||||
{
|
||||
const int msaa = r_msaa->integer;
|
||||
gl.fbMSEnabled = msaa >= 2 && msaa <= 16;
|
||||
gl.fbMSEnabled = msaa >= 2;
|
||||
|
||||
if(gl.fbMSEnabled)
|
||||
{
|
||||
|
|
|
@ -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_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_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_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" },
|
||||
|
|
Loading…
Reference in a new issue