mirror of
https://bitbucket.org/CPMADevs/cnq3
synced 2025-02-08 08:22:06 +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
|
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
|
||||||
|
|
|
@ -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 )
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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" },
|
||||||
|
|
Loading…
Reference in a new issue