Added GLSL ES 1.0 backend for Mesa drivers #90

This commit is contained in:
RobertBeckebans 2014-04-20 16:29:58 +02:00
parent e61eae499c
commit cce21e0d76
15 changed files with 693 additions and 136 deletions

View file

@ -173,7 +173,16 @@ void GL_SelectTexture( int unit );
void GL_Flush(); // flush the GPU command buffer
void GL_Finish(); // wait for the GPU to have executed all commands
void GL_CheckErrors();
// RB begin
bool GL_CheckErrors_( const char* filename, int line );
#if 1 // !defined(RETAIL)
#define GL_CheckErrors() GL_CheckErrors_(__FILE__, __LINE__)
#else
#define GL_CheckErrors() false
#endif
// RB end
wrapperStats_t GL_GetCurrentStats();
void GL_ClearStats();

View file

@ -418,7 +418,8 @@ void idRenderModelOverlay::CreateOverlay( const idRenderModel* model, const idPl
continue;
}
if( tri->staticModelWithJoints != NULL && r_useGPUSkinning.GetBool() )
// RB: added check wether GPU skinning is available at all
if( tri->staticModelWithJoints != NULL && r_useGPUSkinning.GetBool() && glConfig.gpuSkinningAvailable )
{
R_OverlayPointCullSkinned( cullBits.Ptr(), texCoordS.Ptr(), texCoordT.Ptr(), localTextureAxis, tri->verts, tri->numVerts, tri->staticModelWithJoints->jointsInverted );
}
@ -426,6 +427,7 @@ void idRenderModelOverlay::CreateOverlay( const idRenderModel* model, const idPl
{
R_OverlayPointCullStatic( cullBits.Ptr(), texCoordS.Ptr(), texCoordT.Ptr(), localTextureAxis, tri->verts, tri->numVerts );
}
// RB end
// start streaming the indexes
idODSStreamedArray< triIndex_t, 256, SBT_QUAD, 3 > indexesODS( tri->indexes, tri->numIndexes );
@ -607,8 +609,7 @@ static void R_CopyOverlaySurface( idDrawVert* verts, int numVerts, triIndex_t* i
verts[numVerts + i] = sourceVerts[overlayVert.vertexNum];
// RB begin
verts[numVerts + i].SetTexCoordS( overlayVert.st[0] );
verts[numVerts + i].SetTexCoordT( overlayVert.st[1] );
verts[numVerts + i].SetTexCoordNative( overlayVert.st[0], overlayVert.st[1] );
// RB end
}

View file

@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2013-2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -526,7 +527,9 @@ void idMD5Mesh::UpdateSurface( const struct renderEntity_s* ent, const idJointMa
tri->indexCache = deformInfo->staticIndexCache;
tri->numVerts = deformInfo->numOutputVerts;
if( r_useGPUSkinning.GetBool() )
// RB: added check wether GPU skinning is available at all
if( r_useGPUSkinning.GetBool() && glConfig.gpuSkinningAvailable )
{
if( tri->verts != NULL && tri->verts != deformInfo->verts )
{

View file

@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2013-2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -78,46 +79,51 @@ void idRenderProgManager::Init()
{
builtinShaders[i] = -1;
}
// RB: added checks for GPU skinning
struct builtinShaders_t
{
int index;
const char* name;
bool requireGPUSkinningSupport;
} builtins[] =
{
{ BUILTIN_GUI, "gui.vfp" },
{ BUILTIN_COLOR, "color.vfp" },
{ BUILTIN_SIMPLESHADE, "simpleshade.vfp" },
{ BUILTIN_TEXTURED, "texture.vfp" },
{ BUILTIN_TEXTURE_VERTEXCOLOR, "texture_color.vfp" },
{ BUILTIN_TEXTURE_VERTEXCOLOR_SKINNED, "texture_color_skinned.vfp" },
{ BUILTIN_TEXTURE_TEXGEN_VERTEXCOLOR, "texture_color_texgen.vfp" },
{ BUILTIN_INTERACTION, "interaction.vfp" },
{ BUILTIN_INTERACTION_SKINNED, "interaction_skinned.vfp" },
{ BUILTIN_INTERACTION_AMBIENT, "interactionAmbient.vfp" },
{ BUILTIN_INTERACTION_AMBIENT_SKINNED, "interactionAmbient_skinned.vfp" },
{ BUILTIN_ENVIRONMENT, "environment.vfp" },
{ BUILTIN_ENVIRONMENT_SKINNED, "environment_skinned.vfp" },
{ BUILTIN_BUMPY_ENVIRONMENT, "bumpyEnvironment.vfp" },
{ BUILTIN_BUMPY_ENVIRONMENT_SKINNED, "bumpyEnvironment_skinned.vfp" },
{ BUILTIN_GUI, "gui.vfp", false },
{ BUILTIN_COLOR, "color.vfp", false },
{ BUILTIN_SIMPLESHADE, "simpleshade.vfp", false },
{ BUILTIN_TEXTURED, "texture.vfp", false },
{ BUILTIN_TEXTURE_VERTEXCOLOR, "texture_color.vfp", false },
{ BUILTIN_TEXTURE_VERTEXCOLOR_SKINNED, "texture_color_skinned.vfp", true },
{ BUILTIN_TEXTURE_TEXGEN_VERTEXCOLOR, "texture_color_texgen.vfp", false },
{ BUILTIN_INTERACTION, "interaction.vfp", false },
{ BUILTIN_INTERACTION_SKINNED, "interaction_skinned.vfp", true },
{ BUILTIN_INTERACTION_AMBIENT, "interactionAmbient.vfp", false },
{ BUILTIN_INTERACTION_AMBIENT_SKINNED, "interactionAmbient_skinned.vfp", true },
{ BUILTIN_ENVIRONMENT, "environment.vfp", false },
{ BUILTIN_ENVIRONMENT_SKINNED, "environment_skinned.vfp", true },
{ BUILTIN_BUMPY_ENVIRONMENT, "bumpyEnvironment.vfp", false },
{ BUILTIN_BUMPY_ENVIRONMENT_SKINNED, "bumpyEnvironment_skinned.vfp", true },
{ BUILTIN_DEPTH, "depth.vfp" },
{ BUILTIN_DEPTH_SKINNED, "depth_skinned.vfp" },
{ BUILTIN_SHADOW_DEBUG, "shadowDebug.vfp" },
{ BUILTIN_SHADOW_DEBUG_SKINNED, "shadowDebug_skinned.vfp" },
{ BUILTIN_DEPTH, "depth.vfp", false },
{ BUILTIN_DEPTH_SKINNED, "depth_skinned.vfp", true },
{ BUILTIN_SHADOW_DEBUG, "shadowDebug.vfp", false },
{ BUILTIN_SHADOW_DEBUG_SKINNED, "shadowDebug_skinned.vfp", true },
{ BUILTIN_BLENDLIGHT, "blendlight.vfp" },
{ BUILTIN_FOG, "fog.vfp" },
{ BUILTIN_FOG_SKINNED, "fog_skinned.vfp" },
{ BUILTIN_SKYBOX, "skybox.vfp" },
{ BUILTIN_WOBBLESKY, "wobblesky.vfp" },
{ BUILTIN_POSTPROCESS, "postprocess.vfp" },
{ BUILTIN_STEREO_DEGHOST, "stereoDeGhost.vfp" },
{ BUILTIN_STEREO_WARP, "stereoWarp.vfp" },
{ BUILTIN_ZCULL_RECONSTRUCT, "zcullReconstruct.vfp" },
{ BUILTIN_BINK, "bink.vfp" },
{ BUILTIN_BINK_GUI, "bink_gui.vfp" },
{ BUILTIN_STEREO_INTERLACE, "stereoInterlace.vfp" },
{ BUILTIN_MOTION_BLUR, "motionBlur.vfp" },
{ BUILTIN_BLENDLIGHT, "blendlight.vfp", false },
{ BUILTIN_FOG, "fog.vfp", false },
{ BUILTIN_FOG_SKINNED, "fog_skinned.vfp", true },
{ BUILTIN_SKYBOX, "skybox.vfp", false },
{ BUILTIN_WOBBLESKY, "wobblesky.vfp", false },
{ BUILTIN_POSTPROCESS, "postprocess.vfp", false },
{ BUILTIN_STEREO_DEGHOST, "stereoDeGhost.vfp", false },
{ BUILTIN_STEREO_WARP, "stereoWarp.vfp", false },
{ BUILTIN_ZCULL_RECONSTRUCT, "zcullReconstruct.vfp", false },
{ BUILTIN_BINK, "bink.vfp", false },
{ BUILTIN_BINK_GUI, "bink_gui.vfp", false },
{ BUILTIN_STEREO_INTERLACE, "stereoInterlace.vfp", false },
{ BUILTIN_MOTION_BLUR, "motionBlur.vfp", false },
{ BUILTIN_SHADOW, "shadow.vfp", false },
{ BUILTIN_SHADOW_SKINNED, "shadow_skinned.vfp", true },
};
int numBuiltins = sizeof( builtins ) / sizeof( builtins[0] );
vertexShaders.SetNum( numBuiltins );
@ -129,29 +135,69 @@ void idRenderProgManager::Init()
vertexShaders[i].name = builtins[i].name;
fragmentShaders[i].name = builtins[i].name;
builtinShaders[builtins[i].index] = i;
if( builtins[i].requireGPUSkinningSupport && !glConfig.gpuSkinningAvailable )
{
// RB: don't try to load shaders that would break the GLSL compiler in the OpenGL driver
continue;
}
LoadVertexShader( i );
LoadFragmentShader( i );
LoadGLSLProgram( i, i, i );
}
// Special case handling for fastZ shaders
builtinShaders[BUILTIN_SHADOW] = FindVertexShader( "shadow.vp" );
builtinShaders[BUILTIN_SHADOW_SKINNED] = FindVertexShader( "shadow_skinned.vp" );
// special case handling for fastZ shaders
/*
switch( glConfig.driverType )
{
case GLDRV_OPENGL32_CORE_PROFILE:
case GLDRV_OPENGL_ES2:
case GLDRV_OPENGL_ES3:
case GLDRV_OPENGL_MESA:
{
builtinShaders[BUILTIN_SHADOW] = FindVertexShader( "shadow.vp" );
int shadowFragmentShaderIndex = FindFragmentShader( "shadow.fp" );
FindGLSLProgram( "shadow.vp", builtinShaders[BUILTIN_SHADOW], shadowFragmentShaderIndex );
FindGLSLProgram( "shadow.vp", builtinShaders[BUILTIN_SHADOW], -1 );
FindGLSLProgram( "shadow_skinned.vp", builtinShaders[BUILTIN_SHADOW_SKINNED], -1 );
if( glConfig.gpuSkinningAvailable )
{
builtinShaders[BUILTIN_SHADOW_SKINNED] = FindVertexShader( "shadow_skinned.vp" );
int shadowFragmentShaderIndex = FindFragmentShader( "shadow_skinned.fp" );
FindGLSLProgram( "shadow_skinned.vp", builtinShaders[BUILTIN_SHADOW_SKINNED], shadowFragmentShaderIndex );
break;
}
}
default:
{
// fast path on PC
builtinShaders[BUILTIN_SHADOW] = FindVertexShader( "shadow.vp" );
FindGLSLProgram( "shadow.vp", builtinShaders[BUILTIN_SHADOW], -1 );
if( glConfig.gpuSkinningAvailable )
{
builtinShaders[BUILTIN_SHADOW_SKINNED] = FindVertexShader( "shadow_skinned.vp" );
FindGLSLProgram( "shadow_skinned.vp", builtinShaders[BUILTIN_SHADOW_SKINNED], -1 );
}
}
}
*/
glslUniforms.SetNum( RENDERPARM_USER + MAX_GLSL_USER_PARMS, vec4_zero );
vertexShaders[builtinShaders[BUILTIN_TEXTURE_VERTEXCOLOR_SKINNED]].usesJoints = true;
vertexShaders[builtinShaders[BUILTIN_INTERACTION_SKINNED]].usesJoints = true;
vertexShaders[builtinShaders[BUILTIN_INTERACTION_AMBIENT_SKINNED]].usesJoints = true;
vertexShaders[builtinShaders[BUILTIN_ENVIRONMENT_SKINNED]].usesJoints = true;
vertexShaders[builtinShaders[BUILTIN_BUMPY_ENVIRONMENT_SKINNED]].usesJoints = true;
vertexShaders[builtinShaders[BUILTIN_DEPTH_SKINNED]].usesJoints = true;
vertexShaders[builtinShaders[BUILTIN_SHADOW_SKINNED]].usesJoints = true;
vertexShaders[builtinShaders[BUILTIN_SHADOW_DEBUG_SKINNED]].usesJoints = true;
vertexShaders[builtinShaders[BUILTIN_FOG_SKINNED]].usesJoints = true;
if( glConfig.gpuSkinningAvailable )
{
vertexShaders[builtinShaders[BUILTIN_TEXTURE_VERTEXCOLOR_SKINNED]].usesJoints = true;
vertexShaders[builtinShaders[BUILTIN_INTERACTION_SKINNED]].usesJoints = true;
vertexShaders[builtinShaders[BUILTIN_INTERACTION_AMBIENT_SKINNED]].usesJoints = true;
vertexShaders[builtinShaders[BUILTIN_ENVIRONMENT_SKINNED]].usesJoints = true;
vertexShaders[builtinShaders[BUILTIN_BUMPY_ENVIRONMENT_SKINNED]].usesJoints = true;
vertexShaders[builtinShaders[BUILTIN_DEPTH_SKINNED]].usesJoints = true;
vertexShaders[builtinShaders[BUILTIN_SHADOW_SKINNED]].usesJoints = true;
vertexShaders[builtinShaders[BUILTIN_SHADOW_DEBUG_SKINNED]].usesJoints = true;
vertexShaders[builtinShaders[BUILTIN_FOG_SKINNED]].usesJoints = true;
}
cmdSystem->AddCommand( "reloadShaders", R_ReloadShaders, CMD_FL_RENDERER, "reloads shaders" );
}
@ -243,15 +289,17 @@ int idRenderProgManager::FindVertexShader( const char* name )
LoadVertexShader( index );
currentVertexShader = index;
// FIXME: we should really scan the program source code for using rpEnableSkinning but at this
// point we directly load a binary and the program source code is not available on the consoles
if( idStr::Icmp( name, "heatHaze.vfp" ) == 0 ||
idStr::Icmp( name, "heatHazeWithMask.vfp" ) == 0 ||
idStr::Icmp( name, "heatHazeWithMaskAndVertex.vfp" ) == 0 )
// RB: removed idStr::Icmp( name, "heatHaze.vfp" ) == 0 hack
// this requires r_useUniformArrays 1
for( int i = 0; i < vertexShaders[index].uniforms.Num(); i++ )
{
vertexShaders[index].usesJoints = true;
vertexShaders[index].optionalSkinning = true;
if( vertexShaders[index].uniforms[i] == RENDERPARM_ENABLE_SKINNING )
{
vertexShaders[index].usesJoints = true;
vertexShaders[index].optionalSkinning = true;
}
}
// RB end
return index;
}
@ -315,22 +363,54 @@ void idRenderProgManager::LoadFragmentShader( int index )
idRenderProgManager::BindShader
================================================================================================
*/
void idRenderProgManager::BindShader( int vIndex, int fIndex )
// RB begin
void idRenderProgManager::BindShader( int progIndex, int vIndex, int fIndex, bool builtin )
{
if( currentVertexShader == vIndex && currentFragmentShader == fIndex )
{
return;
}
currentVertexShader = vIndex;
currentFragmentShader = fIndex;
// vIndex denotes the GLSL program
if( vIndex >= 0 && vIndex < glslPrograms.Num() )
if( builtin )
{
currentRenderProgram = vIndex;
RENDERLOG_PRINTF( "Binding GLSL Program %s\n", glslPrograms[vIndex].name.c_str() );
qglUseProgram( glslPrograms[vIndex].progId );
currentVertexShader = vIndex;
currentFragmentShader = fIndex;
// vIndex denotes the GLSL program
if( vIndex >= 0 && vIndex < glslPrograms.Num() )
{
currentRenderProgram = vIndex;
RENDERLOG_PRINTF( "Binding GLSL Program %s\n", glslPrograms[vIndex].name.c_str() );
qglUseProgram( glslPrograms[vIndex].progId );
}
}
else
{
if( progIndex == -1 )
{
// RB: FIXME linear search
for( int i = 0; i < glslPrograms.Num(); ++i )
{
if( ( glslPrograms[i].vertexShaderIndex == vIndex ) && ( glslPrograms[i].fragmentShaderIndex == fIndex ) )
{
progIndex = i;
break;
}
}
}
currentVertexShader = vIndex;
currentFragmentShader = fIndex;
if( progIndex >= 0 && progIndex < glslPrograms.Num() )
{
currentRenderProgram = progIndex;
RENDERLOG_PRINTF( "Binding GLSL Program %s\n", glslPrograms[progIndex].name.c_str() );
qglUseProgram( glslPrograms[progIndex].progId );
}
}
}
// RB end
/*
================================================================================================
@ -345,6 +425,13 @@ void idRenderProgManager::Unbind()
qglUseProgram( 0 );
}
// RB begin
bool idRenderProgManager::IsShaderBound() const
{
return ( currentVertexShader != -1 );
}
// RB end
/*
================================================================================================
idRenderProgManager::SetRenderParms

View file

@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2013-2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -147,12 +148,15 @@ public:
int FindVertexShader( const char* name );
int FindFragmentShader( const char* name );
void BindShader( int vIndex, int fIndex );
// RB: added progIndex to handle many custom renderprogs
void BindShader( int progIndex, int vIndex, int fIndex, bool builtin );
// RB end
void BindShader_GUI( )
{
BindShader_Builtin( BUILTIN_GUI );
}
void BindShader_Color( )
{
BindShader_Builtin( BUILTIN_COLOR );
@ -161,14 +165,17 @@ public:
{
BindShader_Builtin( BUILTIN_TEXTURED );
}
void BindShader_TextureVertexColor()
{
BindShader_Builtin( BUILTIN_TEXTURE_VERTEXCOLOR );
};
void BindShader_TextureVertexColorSkinned()
{
BindShader_Builtin( BUILTIN_TEXTURE_VERTEXCOLOR_SKINNED );
};
void BindShader_TextureTexGenVertexColor()
{
BindShader_Builtin( BUILTIN_TEXTURE_TEXGEN_VERTEXCOLOR );
@ -177,14 +184,17 @@ public:
{
BindShader_Builtin( BUILTIN_INTERACTION );
}
void BindShader_InteractionSkinned()
{
BindShader_Builtin( BUILTIN_INTERACTION_SKINNED );
}
void BindShader_InteractionAmbient()
{
BindShader_Builtin( BUILTIN_INTERACTION_AMBIENT );
}
void BindShader_InteractionAmbientSkinned()
{
BindShader_Builtin( BUILTIN_INTERACTION_AMBIENT_SKINNED );
@ -197,14 +207,17 @@ public:
{
BindShader_Builtin( BUILTIN_ENVIRONMENT );
}
void BindShader_EnvironmentSkinned()
{
BindShader_Builtin( BUILTIN_ENVIRONMENT_SKINNED );
}
void BindShader_BumpyEnvironment()
{
BindShader_Builtin( BUILTIN_BUMPY_ENVIRONMENT );
}
void BindShader_BumpyEnvironmentSkinned()
{
BindShader_Builtin( BUILTIN_BUMPY_ENVIRONMENT_SKINNED );
@ -214,22 +227,31 @@ public:
{
BindShader_Builtin( BUILTIN_DEPTH );
}
void BindShader_DepthSkinned()
{
BindShader_Builtin( BUILTIN_DEPTH_SKINNED );
}
void BindShader_Shadow()
{
BindShader( builtinShaders[BUILTIN_SHADOW], -1 );
// RB begin
BindShader( -1, builtinShaders[BUILTIN_SHADOW], -1, true );
// RB end
}
void BindShader_ShadowSkinned()
{
BindShader( builtinShaders[BUILTIN_SHADOW_SKINNED], -1 );
// RB begin
BindShader( -1, builtinShaders[BUILTIN_SHADOW_SKINNED], -1, true );
// RB end
}
void BindShader_ShadowDebug()
{
BindShader_Builtin( BUILTIN_SHADOW_DEBUG );
}
void BindShader_ShadowDebugSkinned()
{
BindShader_Builtin( BUILTIN_SHADOW_DEBUG_SKINNED );
@ -243,42 +265,54 @@ public:
{
BindShader_Builtin( BUILTIN_FOG );
}
void BindShader_FogSkinned()
{
BindShader_Builtin( BUILTIN_FOG_SKINNED );
}
void BindShader_SkyBox()
{
BindShader_Builtin( BUILTIN_SKYBOX );
}
void BindShader_WobbleSky()
{
BindShader_Builtin( BUILTIN_WOBBLESKY );
}
void BindShader_StereoDeGhost()
{
BindShader_Builtin( BUILTIN_STEREO_DEGHOST );
}
void BindShader_StereoWarp()
{
BindShader_Builtin( BUILTIN_STEREO_WARP );
}
void BindShader_StereoInterlace()
{
BindShader_Builtin( BUILTIN_STEREO_INTERLACE );
}
void BindShader_PostProcess()
{
BindShader_Builtin( BUILTIN_POSTPROCESS );
}
#if 0
void BindShader_ZCullReconstruct()
{
BindShader_Builtin( BUILTIN_ZCULL_RECONSTRUCT );
}
#endif
void BindShader_Bink()
{
BindShader_Builtin( BUILTIN_BINK );
}
void BindShader_BinkGUI()
{
BindShader_Builtin( BUILTIN_BINK_GUI );
@ -302,6 +336,10 @@ public:
// unbind the currently bound render program
void Unbind();
// RB begin
bool IsShaderBound() const;
// RB end
// this should only be called via the reload shader console command
void LoadAllShaders();
void KillAllShaders();
@ -365,7 +403,7 @@ protected:
int builtinShaders[MAX_BUILTINS];
void BindShader_Builtin( int i )
{
BindShader( builtinShaders[i], builtinShaders[i] );
BindShader( -1, builtinShaders[i], builtinShaders[i], true );
}
bool CompileGLSL( GLenum target, const char* name );

View file

@ -3,7 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2012 Robert Beckebans
Copyright (C) 2013-2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -34,10 +34,15 @@ If you have questions concerning this license or the applicable additional terms
idCVar r_skipStripDeadCode( "r_skipStripDeadCode", "0", CVAR_BOOL, "Skip stripping dead code" );
idCVar r_useUniformArrays( "r_useUniformArrays", "1", CVAR_BOOL, "" );
// DG: the AMD drivers output a lot of useless warnings which are fscking annoying, added this CVar to suppress them
idCVar r_displayGLSLCompilerMessages( "r_displayGLSLCompilerMessages", "1", CVAR_BOOL | CVAR_ARCHIVE, "Show info messages the GPU driver outputs when compiling the shaders" );
// DG end
// RB begin
idCVar r_alwaysExportGLSL( "r_alwaysExportGLSL", "1", CVAR_BOOL, "" );
// RB end
#define VERTEX_UNIFORM_ARRAY_NAME "_va_"
#define FRAGMENT_UNIFORM_ARRAY_NAME "_fa_"
@ -45,6 +50,11 @@ static const int AT_VS_IN = BIT( 1 );
static const int AT_VS_OUT = BIT( 2 );
static const int AT_PS_IN = BIT( 3 );
static const int AT_PS_OUT = BIT( 4 );
// RB begin
static const int AT_VS_OUT_RESERVED = BIT( 5 );
static const int AT_PS_IN_RESERVED = BIT( 6 );
static const int AT_PS_OUT_RESERVED = BIT( 7 );
// RB end
struct idCGBlock
{
@ -106,7 +116,7 @@ attribInfo_t attribsPC[] =
{ "float4", "color2", "COLOR1", "in_Color2", PC_ATTRIB_INDEX_COLOR2, AT_VS_IN, VERTEX_MASK_COLOR2 },
// pre-defined vertex program output
{ "float4", "position", "POSITION", "gl_Position", 0, AT_VS_OUT, 0 },
{ "float4", "position", "POSITION", "gl_Position", 0, AT_VS_OUT | AT_VS_OUT_RESERVED, 0 },
{ "float", "clip0", "CLP0", "gl_ClipDistance[0]", 0, AT_VS_OUT, 0 },
{ "float", "clip1", "CLP1", "gl_ClipDistance[1]", 0, AT_VS_OUT, 0 },
{ "float", "clip2", "CLP2", "gl_ClipDistance[2]", 0, AT_VS_OUT, 0 },
@ -115,32 +125,38 @@ attribInfo_t attribsPC[] =
{ "float", "clip5", "CLP5", "gl_ClipDistance[5]", 0, AT_VS_OUT, 0 },
// pre-defined fragment program input
{ "float4", "position", "WPOS", "gl_FragCoord", 0, AT_PS_IN, 0 },
{ "half4", "hposition", "WPOS", "gl_FragCoord", 0, AT_PS_IN, 0 },
{ "float", "facing", "FACE", "gl_FrontFacing", 0, AT_PS_IN, 0 },
{ "float4", "position", "WPOS", "gl_FragCoord", 0, AT_PS_IN | AT_PS_IN_RESERVED, 0 },
{ "half4", "hposition", "WPOS", "gl_FragCoord", 0, AT_PS_IN | AT_PS_IN_RESERVED, 0 },
{ "float", "facing", "FACE", "gl_FrontFacing", 0, AT_PS_IN | AT_PS_IN_RESERVED, 0 },
// fragment program output
{ "float4", "color", "COLOR", "gl_FragColor", 0, AT_PS_OUT, 0 }, // GLSL version 1.2 doesn't allow for custom color name mappings
{ "half4", "hcolor", "COLOR", "gl_FragColor", 0, AT_PS_OUT, 0 },
{ "float4", "color0", "COLOR0", "gl_FragColor", 0, AT_PS_OUT, 0 },
{ "float4", "color1", "COLOR1", "gl_FragColor", 1, AT_PS_OUT, 0 },
{ "float4", "color2", "COLOR2", "gl_FragColor", 2, AT_PS_OUT, 0 },
{ "float4", "color3", "COLOR3", "gl_FragColor", 3, AT_PS_OUT, 0 },
{ "float", "depth", "DEPTH", "gl_FragDepth", 4, AT_PS_OUT, 0 },
{ "float4", "color", "COLOR", "gl_FragColor", 0, AT_PS_OUT | AT_PS_OUT_RESERVED, 0 }, // GLSL version 1.2 doesn't allow for custom color name mappings
{ "half4", "hcolor", "COLOR", "gl_FragColor", 0, AT_PS_OUT | AT_PS_OUT_RESERVED, 0 },
{ "float4", "color0", "COLOR0", "gl_FragColor", 0, AT_PS_OUT | AT_PS_OUT_RESERVED, 0 },
{ "float4", "color1", "COLOR1", "gl_FragColor", 1, AT_PS_OUT | AT_PS_OUT_RESERVED, 0 },
{ "float4", "color2", "COLOR2", "gl_FragColor", 2, AT_PS_OUT | AT_PS_OUT_RESERVED, 0 },
{ "float4", "color3", "COLOR3", "gl_FragColor", 3, AT_PS_OUT | AT_PS_OUT_RESERVED, 0 },
{ "float", "depth", "DEPTH", "gl_FragDepth", 4, AT_PS_OUT | AT_PS_OUT_RESERVED, 0 },
// vertex to fragment program pass through
{ "float4", "color", "COLOR", "gl_FrontColor", 0, AT_VS_OUT, 0 },
{ "float4", "color0", "COLOR0", "gl_FrontColor", 0, AT_VS_OUT, 0 },
{ "float4", "color1", "COLOR1", "gl_FrontSecondaryColor", 0, AT_VS_OUT, 0 },
#if 0 //defined(USE_GLES2)
{ "float4", "color", "COLOR", "vofi_FrontColor", 0, AT_VS_OUT | AT_VS_OUT_RESERVED, 0 },
{ "float4", "color0", "COLOR0", "vofi_Color", 0, AT_VS_OUT | AT_VS_OUT_RESERVED, 0 },
{ "float4", "color1", "COLOR1", "vofi_FrontSecondaryColor", 0, AT_VS_OUT | AT_VS_OUT_RESERVED, 0 },
#else
{ "float4", "color", "COLOR", "vofi_Color", 0, AT_VS_OUT, 0 },
{ "float4", "color0", "COLOR0", "vofi_Color", 0, AT_VS_OUT, 0 },
{ "float4", "color1", "COLOR1", "vofi_SecondaryColor", 0, AT_VS_OUT, 0 },
#endif
{ "float4", "color", "COLOR", "gl_Color", 0, AT_PS_IN, 0 },
{ "float4", "color0", "COLOR0", "gl_Color", 0, AT_PS_IN, 0 },
{ "float4", "color1", "COLOR1", "gl_SecondaryColor", 0, AT_PS_IN, 0 },
{ "float4", "color", "COLOR", "vofi_Color", 0, AT_PS_IN, 0 },
{ "float4", "color0", "COLOR0", "vofi_Color", 0, AT_PS_IN, 0 },
{ "float4", "color1", "COLOR1", "vofi_SecondaryColor", 0, AT_PS_IN, 0 },
{ "half4", "hcolor", "COLOR", "gl_Color", 0, AT_PS_IN, 0 },
{ "half4", "hcolor0", "COLOR0", "gl_Color", 0, AT_PS_IN, 0 },
{ "half4", "hcolor1", "COLOR1", "gl_SecondaryColor", 0, AT_PS_IN, 0 },
{ "half4", "hcolor", "COLOR", "vofi_Color", 0, AT_PS_IN, 0 },
{ "half4", "hcolor0", "COLOR0", "vofi_Color", 0, AT_PS_IN, 0 },
{ "half4", "hcolor1", "COLOR1", "vofi_SecondaryColor", 0, AT_PS_IN, 0 },
{ "float4", "texcoord0", "TEXCOORD0_centroid", "vofi_TexCoord0", 0, AT_PS_IN, 0 },
{ "float4", "texcoord1", "TEXCOORD1_centroid", "vofi_TexCoord1", 0, AT_PS_IN, 0 },
@ -316,7 +332,20 @@ idStr StripDeadCode( const idStr& in, const char* name )
src.LoadMemory( in.c_str(), in.Length(), name );
src.AddDefine( "PC" );
idList< idCGBlock, TAG_RENDERPROG > blocks;
switch( glConfig.driverType )
{
case GLDRV_OPENGL_ES2:
case GLDRV_OPENGL_ES3:
src.AddDefine( "GLES2" );
break;
}
if( glConfig.gpuSkinningAvailable )
{
src.AddDefine( "USE_GPU_SKINNING" );
}
idList< idCGBlock > blocks;
blocks.SetNum( 100 );
@ -555,7 +584,53 @@ struct typeConversion_t
{ NULL, NULL }
};
const char* vertexInsert =
// RB begin
#if defined(USE_GLES2)
const char* vertexInsert_GLSL_ES_1_0 =
{
"#version 100\n"
"#define GLES2\n"
"#define PC\n"
"precision mediump float;\n"
"\n"
"float saturate( float v ) { return clamp( v, 0.0, 1.0 ); }\n"
"vec2 saturate( vec2 v ) { return clamp( v, 0.0, 1.0 ); }\n"
"vec3 saturate( vec3 v ) { return clamp( v, 0.0, 1.0 ); }\n"
"vec4 saturate( vec4 v ) { return clamp( v, 0.0, 1.0 ); }\n"
//"vec4 tex2Dlod( sampler2D sampler, vec4 texcoord ) { return textureLod( sampler, texcoord.xy, texcoord.w ); }\n"
"\n"
};
#else
const char* vertexInsert_GLSL_ES_1_0 =
{
"#version 100\n"
#if !defined(USE_MESA)
"#define GLES2\n"
#endif
"#define PC\n"
#if 1 //defined(__ANDROID__)
"precision mediump float;\n"
#else
"precision highp float;\n"
#endif
#if defined(USE_GPU_SKINNING) && !defined(__ANDROID__)
"#extension GL_ARB_gpu_shader5 : enable\n"
#endif
"\n"
"float saturate( float v ) { return clamp( v, 0.0, 1.0 ); }\n"
"vec2 saturate( vec2 v ) { return clamp( v, 0.0, 1.0 ); }\n"
"vec3 saturate( vec3 v ) { return clamp( v, 0.0, 1.0 ); }\n"
"vec4 saturate( vec4 v ) { return clamp( v, 0.0, 1.0 ); }\n"
//"vec4 tex2Dlod( sampler2D sampler, vec4 texcoord ) { return textureLod( sampler, texcoord.xy, texcoord.w ); }\n"
"\n"
};
#endif // #if defined(USE_GLES2)
const char* vertexInsert_GLSL_1_50 =
{
"#version 150\n"
"#define PC\n"
@ -568,7 +643,106 @@ const char* vertexInsert =
"\n"
};
const char* fragmentInsert =
#if defined(USE_GLES2)
const char* fragmentInsert_GLSL_ES_1_0 =
{
"#version 100\n"
"#define GLES2\n"
"#define PC\n"
"precision mediump float;\n"
"#extension GL_OES_standard_derivatives : enable\n"
"\n"
"void clip( float v ) { if ( v < 0.0 ) { discard; } }\n"
"void clip( vec2 v ) { if ( any( lessThan( v, vec2( 0.0 ) ) ) ) { discard; } }\n"
"void clip( vec3 v ) { if ( any( lessThan( v, vec3( 0.0 ) ) ) ) { discard; } }\n"
"void clip( vec4 v ) { if ( any( lessThan( v, vec4( 0.0 ) ) ) ) { discard; } }\n"
"\n"
"float saturate( float v ) { return clamp( v, 0.0, 1.0 ); }\n"
"vec2 saturate( vec2 v ) { return clamp( v, 0.0, 1.0 ); }\n"
"vec3 saturate( vec3 v ) { return clamp( v, 0.0, 1.0 ); }\n"
"vec4 saturate( vec4 v ) { return clamp( v, 0.0, 1.0 ); }\n"
"\n"
"vec4 tex2D( sampler2D sampler, vec2 texcoord ) { return texture2D( sampler, texcoord.xy ); }\n"
//"vec4 tex2D( sampler2DShadow sampler, vec3 texcoord ) { return vec4( texture( sampler, texcoord.xyz ) ); }\n"
"\n"
//"vec4 tex2D( sampler2D sampler, vec2 texcoord, vec2 dx, vec2 dy ) { return textureGrad( sampler, texcoord.xy, dx, dy ); }\n"
//"vec4 tex2D( sampler2DShadow sampler, vec3 texcoord, vec2 dx, vec2 dy ) { return vec4( textureGrad( sampler, texcoord.xyz, dx, dy ) ); }\n"
//"\n"
"vec4 texCUBE( samplerCube sampler, vec3 texcoord ) { return textureCube( sampler, texcoord.xyz ); }\n"
//"vec4 texCUBE( samplerCubeShadow sampler, vec4 texcoord ) { return vec4( textureCube( sampler, texcoord.xyzw ) ); }\n"
"\n"
//"vec4 tex1Dproj( sampler1D sampler, vec2 texcoord ) { return textureProj( sampler, texcoord ); }\n"
"vec4 tex2Dproj( sampler2D sampler, vec3 texcoord ) { return texture2DProj( sampler, texcoord ); }\n"
//"vec4 tex3Dproj( sampler3D sampler, vec4 texcoord ) { return textureProj( sampler, texcoord ); }\n"
"\n"
//"vec4 tex1Dbias( sampler1D sampler, vec4 texcoord ) { return texture( sampler, texcoord.x, texcoord.w ); }\n"
//"vec4 tex2Dbias( sampler2D sampler, vec4 texcoord ) { return texture( sampler, texcoord.xy, texcoord.w ); }\n"
//"vec4 tex3Dbias( sampler3D sampler, vec4 texcoord ) { return texture( sampler, texcoord.xyz, texcoord.w ); }\n"
//"vec4 texCUBEbias( samplerCube sampler, vec4 texcoord ) { return texture( sampler, texcoord.xyz, texcoord.w ); }\n"
//"\n"
//"vec4 tex1Dlod( sampler1D sampler, vec4 texcoord ) { return textureLod( sampler, texcoord.x, texcoord.w ); }\n"
//"vec4 tex2Dlod( sampler2D sampler, vec4 texcoord ) { return textureLod( sampler, texcoord.xy, texcoord.w ); }\n"
//"vec4 tex3Dlod( sampler3D sampler, vec4 texcoord ) { return textureLod( sampler, texcoord.xyz, texcoord.w ); }\n"
//"vec4 texCUBElod( samplerCube sampler, vec4 texcoord ) { return textureLod( sampler, texcoord.xyz, texcoord.w ); }\n"
//"\n"
};
#else
const char* fragmentInsert_GLSL_ES_1_0 =
{
"#version 100\n"
#if !defined(USE_MESA)
"#define GLES2\n"
#endif
"#define PC\n"
#if 1 //defined(__ANDROID__)
"precision mediump float;\n"
//"#extension GL_OES_standard_derivatives : enable\n"
#else
"precision highp float;\n"
#endif
"\n"
"void clip( float v ) { if ( v < 0.0 ) { discard; } }\n"
"void clip( vec2 v ) { if ( any( lessThan( v, vec2( 0.0 ) ) ) ) { discard; } }\n"
"void clip( vec3 v ) { if ( any( lessThan( v, vec3( 0.0 ) ) ) ) { discard; } }\n"
"void clip( vec4 v ) { if ( any( lessThan( v, vec4( 0.0 ) ) ) ) { discard; } }\n"
"\n"
"float saturate( float v ) { return clamp( v, 0.0, 1.0 ); }\n"
"vec2 saturate( vec2 v ) { return clamp( v, 0.0, 1.0 ); }\n"
"vec3 saturate( vec3 v ) { return clamp( v, 0.0, 1.0 ); }\n"
"vec4 saturate( vec4 v ) { return clamp( v, 0.0, 1.0 ); }\n"
"\n"
"vec4 tex2D( sampler2D sampler, vec2 texcoord ) { return texture2D( sampler, texcoord.xy ); }\n"
//"vec4 tex2D( sampler2DShadow sampler, vec3 texcoord ) { return vec4( texture( sampler, texcoord.xyz ) ); }\n"
"\n"
//"vec4 tex2D( sampler2D sampler, vec2 texcoord, vec2 dx, vec2 dy ) { return textureGrad( sampler, texcoord.xy, dx, dy ); }\n"
//"vec4 tex2D( sampler2DShadow sampler, vec3 texcoord, vec2 dx, vec2 dy ) { return vec4( textureGrad( sampler, texcoord.xyz, dx, dy ) ); }\n"
//"\n"
"vec4 texCUBE( samplerCube sampler, vec3 texcoord ) { return textureCube( sampler, texcoord.xyz ); }\n"
//"vec4 texCUBE( samplerCubeShadow sampler, vec4 texcoord ) { return vec4( textureCube( sampler, texcoord.xyzw ) ); }\n"
"\n"
//"vec4 tex1Dproj( sampler1D sampler, vec2 texcoord ) { return textureProj( sampler, texcoord ); }\n"
"vec4 tex2Dproj( sampler2D sampler, vec3 texcoord ) { return texture2DProj( sampler, texcoord ); }\n"
//"vec4 tex3Dproj( sampler3D sampler, vec4 texcoord ) { return textureProj( sampler, texcoord ); }\n"
"\n"
//"vec4 tex1Dbias( sampler1D sampler, vec4 texcoord ) { return texture( sampler, texcoord.x, texcoord.w ); }\n"
//"vec4 tex2Dbias( sampler2D sampler, vec4 texcoord ) { return texture( sampler, texcoord.xy, texcoord.w ); }\n"
//"vec4 tex3Dbias( sampler3D sampler, vec4 texcoord ) { return texture( sampler, texcoord.xyz, texcoord.w ); }\n"
//"vec4 texCUBEbias( samplerCube sampler, vec4 texcoord ) { return texture( sampler, texcoord.xyz, texcoord.w ); }\n"
//"\n"
//"vec4 tex1Dlod( sampler1D sampler, vec4 texcoord ) { return textureLod( sampler, texcoord.x, texcoord.w ); }\n"
//"vec4 tex2Dlod( sampler2D sampler, vec4 texcoord ) { return textureLod( sampler, texcoord.xy, texcoord.w ); }\n"
//"vec4 tex3Dlod( sampler3D sampler, vec4 texcoord ) { return textureLod( sampler, texcoord.xyz, texcoord.w ); }\n"
//"vec4 texCUBElod( samplerCube sampler, vec4 texcoord ) { return textureLod( sampler, texcoord.xyz, texcoord.w ); }\n"
//"\n"
};
#endif // #if defined(USE_GLES2)
const char* fragmentInsert_GLSL_1_50 =
{
"#version 150\n"
"#define PC\n"
@ -607,6 +781,7 @@ const char* fragmentInsert =
"vec4 texCUBElod( samplerCube sampler, vec4 texcoord ) { return textureLod( sampler, texcoord.xyz, texcoord.w ); }\n"
"\n"
};
// RB end
struct builtinConversion_t
{
@ -636,7 +811,7 @@ struct inOutVariable_t
ParseInOutStruct
========================
*/
void ParseInOutStruct( idLexer& src, int attribType, idList< inOutVariable_t >& inOutVars )
void ParseInOutStruct( idLexer& src, int attribType, int attribIgnoreType, idList< inOutVariable_t >& inOutVars )
{
src.ExpectTokenString( "{" );
@ -694,6 +869,31 @@ void ParseInOutStruct( idLexer& src, int attribType, idList< inOutVariable_t >&
}
}
// RB: ignore reserved builtin gl_ uniforms
switch( glConfig.driverType )
{
case GLDRV_OPENGL32_CORE_PROFILE:
case GLDRV_OPENGL_ES2:
case GLDRV_OPENGL_ES3:
case GLDRV_OPENGL_MESA:
{
for( int i = 0; attribsPC[i].semantic != NULL; i++ )
{
if( var.nameGLSL.Cmp( attribsPC[i].glsl ) == 0 )
{
if( ( attribsPC[i].flags & attribIgnoreType ) != 0 )
{
var.declareInOut = false;
break;
}
}
}
break;
}
}
// RB end
inOutVars.Append( var );
}
@ -748,39 +948,91 @@ idStr ConvertCG2GLSL( const idStr& in, const char* name, bool isVertexProgram, i
{
if( src.CheckTokenString( "VS_IN" ) )
{
ParseInOutStruct( src, AT_VS_IN, varsIn );
ParseInOutStruct( src, AT_VS_IN, 0, varsIn );
program += "\n\n";
for( int i = 0; i < varsIn.Num(); i++ )
{
if( varsIn[i].declareInOut )
{
program += "in " + varsIn[i].type + " " + varsIn[i].nameGLSL + ";\n";
// RB begin
switch( glConfig.driverType )
{
case GLDRV_OPENGL_ES2:
case GLDRV_OPENGL_ES3:
case GLDRV_OPENGL_MESA:
{
program += "attribute " + varsIn[i].type + " " + varsIn[i].nameGLSL + ";\n";
break;
}
default:
{
program += "in " + varsIn[i].type + " " + varsIn[i].nameGLSL + ";\n";
break;
}
}
// RB end
}
}
continue;
}
else if( src.CheckTokenString( "VS_OUT" ) )
{
ParseInOutStruct( src, AT_VS_OUT, varsOut );
// RB begin
ParseInOutStruct( src, AT_VS_OUT, AT_VS_OUT_RESERVED, varsOut );
// RB end
program += "\n";
for( int i = 0; i < varsOut.Num(); i++ )
{
if( varsOut[i].declareInOut )
{
program += "out " + varsOut[i].type + " " + varsOut[i].nameGLSL + ";\n";
// RB begin
switch( glConfig.driverType )
{
case GLDRV_OPENGL_ES2:
case GLDRV_OPENGL_ES3:
case GLDRV_OPENGL_MESA:
{
program += "varying " + varsOut[i].type + " " + varsOut[i].nameGLSL + ";\n";
break;
}
default:
{
program += "out " + varsOut[i].type + " " + varsOut[i].nameGLSL + ";\n";
break;
}
}
// RB end
}
}
continue;
}
else if( src.CheckTokenString( "PS_IN" ) )
{
ParseInOutStruct( src, AT_PS_IN, varsIn );
ParseInOutStruct( src, AT_PS_IN, AT_PS_IN_RESERVED, varsIn );
program += "\n\n";
for( int i = 0; i < varsIn.Num(); i++ )
{
if( varsIn[i].declareInOut )
{
program += "in " + varsIn[i].type + " " + varsIn[i].nameGLSL + ";\n";
// RB begin
switch( glConfig.driverType )
{
case GLDRV_OPENGL_ES2:
case GLDRV_OPENGL_ES3:
case GLDRV_OPENGL_MESA:
{
program += "varying " + varsIn[i].type + " " + varsIn[i].nameGLSL + ";\n";
break;
}
default:
program += "in " + varsIn[i].type + " " + varsIn[i].nameGLSL + ";\n";
break;
}
// RB end
}
}
inOutVariable_t var;
@ -792,7 +1044,10 @@ idStr ConvertCG2GLSL( const idStr& in, const char* name, bool isVertexProgram, i
}
else if( src.CheckTokenString( "PS_OUT" ) )
{
ParseInOutStruct( src, AT_PS_OUT, varsOut );
// RB begin
ParseInOutStruct( src, AT_PS_OUT, AT_PS_OUT_RESERVED, varsOut );
// RB end
program += "\n";
for( int i = 0; i < varsOut.Num(); i++ )
{
@ -994,16 +1249,52 @@ idStr ConvertCG2GLSL( const idStr& in, const char* name, bool isVertexProgram, i
idStr out;
// RB: changed to allow multiple versions of GLSL
if( isVertexProgram )
{
out.ReAllocate( idStr::Length( vertexInsert ) + in.Length() * 2, false );
out += vertexInsert;
switch( glConfig.driverType )
{
case GLDRV_OPENGL_ES2:
case GLDRV_OPENGL_ES3:
case GLDRV_OPENGL_MESA:
{
out.ReAllocate( idStr::Length( vertexInsert_GLSL_ES_1_0 ) + in.Length() * 2, false );
out += vertexInsert_GLSL_ES_1_0;
break;
}
default:
{
out.ReAllocate( idStr::Length( vertexInsert_GLSL_1_50 ) + in.Length() * 2, false );
out += vertexInsert_GLSL_1_50;
break;
}
}
}
else
{
out.ReAllocate( idStr::Length( fragmentInsert ) + in.Length() * 2, false );
out += fragmentInsert;
switch( glConfig.driverType )
{
case GLDRV_OPENGL_ES2:
case GLDRV_OPENGL_ES3:
case GLDRV_OPENGL_MESA:
{
out.ReAllocate( idStr::Length( fragmentInsert_GLSL_ES_1_0 ) + in.Length() * 2, false );
out += fragmentInsert_GLSL_ES_1_0;
break;
}
default:
{
out.ReAllocate( idStr::Length( fragmentInsert_GLSL_1_50 ) + in.Length() * 2, false );
out += fragmentInsert_GLSL_1_50;
break;
}
}
}
// RB end
if( uniformList.Num() > 0 )
{
@ -1053,9 +1344,26 @@ GLuint idRenderProgManager::LoadGLSLShader( GLenum target, const char* name, idL
inFile.StripFileExtension();
outFileHLSL.Format( "renderprogs/hlsl/%s", name );
outFileHLSL.StripFileExtension();
outFileGLSL.Format( "renderprogs/glsl/%s", name );
switch( glConfig.driverType )
{
case GLDRV_OPENGL_ES2:
case GLDRV_OPENGL_ES3:
case GLDRV_OPENGL_MESA:
{
outFileGLSL.Format( "renderprogs/glsles-1.0/%s", name );
outFileUniforms.Format( "renderprogs/glsles-1.0/%s", name );
break;
}
default:
{
outFileGLSL.Format( "renderprogs/glsl-1.50/%s", name );
outFileUniforms.Format( "renderprogs/glsl-1.50/%s", name );
}
}
outFileGLSL.StripFileExtension();
outFileUniforms.Format( "renderprogs/glsl/%s", name );
outFileUniforms.StripFileExtension();
// RB end
@ -1084,7 +1392,7 @@ GLuint idRenderProgManager::LoadGLSLShader( GLenum target, const char* name, idL
// if the glsl file doesn't exist or we have a newer HLSL file we need to recreate the glsl file.
idStr programGLSL;
idStr programUniforms;
if( ( glslFileLength <= 0 ) || ( hlslTimeStamp > glslTimeStamp ) )
if( ( glslFileLength <= 0 ) || ( hlslTimeStamp > glslTimeStamp ) || r_alwaysExportGLSL.GetBool() )
{
if( hlslFileLength <= 0 )
{
@ -1464,12 +1772,17 @@ void idRenderProgManager::LoadGLSLProgram( const int programIndex, const int ver
prog.uniformLocations.SortWithTemplate( idSort_QuickUniforms() );
}
// get the uniform buffer binding for skinning joint matrices
GLint blockIndex = qglGetUniformBlockIndex( program, "matrices_ubo" );
if( blockIndex != -1 )
// RB: only load joint uniform buffers if available
if( glConfig.gpuSkinningAvailable )
{
qglUniformBlockBinding( program, blockIndex, 0 );
// get the uniform buffer binding for skinning joint matrices
GLint blockIndex = qglGetUniformBlockIndex( program, "matrices_ubo" );
if( blockIndex != -1 )
{
qglUniformBlockBinding( program, blockIndex, 0 );
}
}
// RB end
// set the texture unit locations once for the render program. We only need to do this once since we only link the program once
qglUseProgram( program );

View file

@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2013-2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -84,6 +85,18 @@ enum graphicsVendor_t
VENDOR_INTEL
};
// RB: similar to Q3A - allow separate codepaths between OpenGL 3.x, OpenGL ES versions
enum graphicsDriverType_t
{
GLDRV_OPENGL3X, // best for development with legacy OpenGL tools
GLDRV_OPENGL32_COMPATIBILITY_PROFILE,
GLDRV_OPENGL32_CORE_PROFILE, // best for shipping to PC
GLDRV_OPENGL_ES2,
GLDRV_OPENGL_ES3,
GLDRV_OPENGL_MESA, // fear this, it is probably the best to disable GPU skinning and run shaders in GLSL ES 1.0
};
// RB end
// Contains variables specific to the OpenGL configuration being run right now.
// These are constant once the OpenGL subsystem is initialized.
struct glconfig_t
@ -97,6 +110,9 @@ struct glconfig_t
float glVersion; // atof( version_string )
graphicsVendor_t vendor;
// RB begin
graphicsDriverType_t driverType;
// RB end
int maxTextureSize; // queried from GL
int maxTextureCoords;
@ -130,6 +146,14 @@ struct glconfig_t
bool debugOutputAvailable;
bool swapControlTearAvailable;
// RB begin
bool gremedyStringMarkerAvailable;
bool vertexHalfFloatAvailable;
// only true with uniform buffer support and an OpenGL driver that supports GLSL >= 1.50
bool gpuSkinningAvailable;
// RB end
stereo3DMode_t stereo3Dmode;
int nativeScreenWidth; // this is the native screen width resolution of the renderer
int nativeScreenHeight; // this is the native screen height resolution of the renderer
@ -148,7 +172,11 @@ struct glconfig_t
float pixelAspect;
// RB begin
#if !defined(__ANDROID__)
GLuint global_vao;
#endif
// RB end
};

View file

@ -3,7 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2012 Robert Beckebans
Copyright (C) 2012-2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -561,6 +561,8 @@ static void R_CheckPortableExtensions()
glConfig.uniformBufferOffsetAlignment = 256;
}
}
// RB: make GPU skinning optional for weak OpenGL drivers
glConfig.gpuSkinningAvailable = glConfig.uniformBufferAvailable && ( glConfig.driverType == GLDRV_OPENGL3X || glConfig.driverType == GLDRV_OPENGL32_CORE_PROFILE || glConfig.driverType == GLDRV_OPENGL32_COMPATIBILITY_PROFILE );
// ATI_separate_stencil / OpenGL 2.0 separate stencil
glConfig.twoSidedStencilAvailable = ( glConfig.glVersion >= 2.0f ) || R_CheckExtension( "GL_ATI_separate_stencil" );
@ -987,20 +989,29 @@ void R_InitOpenGL()
GL_CheckErrors
==================
*/
void GL_CheckErrors()
// RB: added filename, line parms
bool GL_CheckErrors_( const char* filename, int line )
{
int err;
char s[64];
int i;
if( r_ignoreGLErrors.GetBool() )
{
return false;
}
// check for up to 10 errors pending
bool error = false;
for( i = 0 ; i < 10 ; i++ )
{
err = qglGetError();
if( err == GL_NO_ERROR )
{
return;
break;
}
error = true;
switch( err )
{
case GL_INVALID_ENUM:
@ -1012,12 +1023,14 @@ void GL_CheckErrors()
case GL_INVALID_OPERATION:
strcpy( s, "GL_INVALID_OPERATION" );
break;
#if !defined(USE_GLES2) && !defined(USE_GLES3)
case GL_STACK_OVERFLOW:
strcpy( s, "GL_STACK_OVERFLOW" );
break;
case GL_STACK_UNDERFLOW:
strcpy( s, "GL_STACK_UNDERFLOW" );
break;
#endif
case GL_OUT_OF_MEMORY:
strcpy( s, "GL_OUT_OF_MEMORY" );
break;
@ -1026,12 +1039,12 @@ void GL_CheckErrors()
break;
}
if( !r_ignoreGLErrors.GetBool() )
{
common->Printf( "GL_CheckErrors: %s\n", s );
}
common->Printf( "caught OpenGL error: %s in file %s line %i\n", s, filename, line );
}
return error;
}
// RB end
/*
=====================
@ -1870,8 +1883,8 @@ void GfxInfo_f( const idCmdArgs& args )
common->Printf( "GL_MAX_TEXTURE_IMAGE_UNITS_ARB: %d\n", glConfig.maxTextureImageUnits );
// print all the display adapters, monitors, and video modes
void DumpAllDisplayDevices();
DumpAllDisplayDevices();
//void DumpAllDisplayDevices();
//DumpAllDisplayDevices();
common->Printf( "\nPIXELFORMAT: color(%d-bits) Z(%d-bit) stencil(%d-bits)\n", glConfig.colorBits, glConfig.depthBits, glConfig.stencilBits );
common->Printf( "MODE: %d, %d x %d %s hz:", r_vidMode.GetInteger(), renderSystem->GetWidth(), renderSystem->GetHeight(), fsstrings[r_fullscreen.GetBool()] );
@ -1887,7 +1900,7 @@ void GfxInfo_f( const idCmdArgs& args )
common->Printf( "-------\n" );
// RB begin
#if defined(_WIN32)
#if defined(_WIN32) && !defined(USE_GLES2)
// WGL_EXT_swap_interval
typedef BOOL ( WINAPI * PFNWGLSWAPINTERVALEXTPROC )( int interval );
extern PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
@ -1957,6 +1970,15 @@ void GfxInfo_f( const idCmdArgs& args )
renderSystem->GetPhysicalScreenWidthInCentimeters(), renderSystem->GetPhysicalScreenWidthInCentimeters() / 2.54f
* sqrt( ( float )( 16 * 16 + 9 * 9 ) ) / 16.0f );
}
if( glConfig.gpuSkinningAvailable )
{
common->Printf( S_COLOR_GREEN "GPU skeletal animation available\n" );
}
else
{
common->Printf( S_COLOR_GREEN "GPU skeletal animation not available (slower CPU path active)\n" );
}
}
/*

View file

@ -258,6 +258,10 @@ void RB_DrawElementsWithCounters( const drawSurf_t* surf )
vertOffset / sizeof( idDrawVert ) );
// RB: added stats
backEnd.pc.c_drawElements++;
backEnd.pc.c_drawIndexes += surf->numIndexes;
// RB end
}
/*
@ -1205,7 +1209,7 @@ static void RB_RenderInteractions( const drawSurf_t* surfList, const viewLight_t
// of benefit to trying to sort by materials.
//---------------------------------
static const int MAX_INTERACTIONS_PER_LIGHT = 1024;
static const int MAX_COMPLEX_INTERACTIONS_PER_LIGHT = 128;
static const int MAX_COMPLEX_INTERACTIONS_PER_LIGHT = 256;
idStaticList< const drawSurf_t*, MAX_INTERACTIONS_PER_LIGHT > allSurfaces;
idStaticList< const drawSurf_t*, MAX_COMPLEX_INTERACTIONS_PER_LIGHT > complexSurfaces;
for( const drawSurf_t* walk = surfList; walk != NULL; walk = walk->nextOnLight )
@ -1813,6 +1817,11 @@ static void RB_StencilShadowPass( const drawSurf_t* drawSurfs, const viewLight_t
qglDrawElementsBaseVertex( GL_TRIANGLES, r_singleTriangle.GetBool() ? 3 : drawSurf->numIndexes, GL_INDEX_TYPE, ( triIndex_t* )indexOffset, vertOffset / sizeof( idShadowVert ) );
}
// RB: added stats
backEnd.pc.c_shadowElements++;
backEnd.pc.c_shadowIndexes += drawSurf->numIndexes;
// RB end
if( !renderZPass && r_useStencilShadowPreload.GetBool() )
{
// render again with Z-pass
@ -1827,6 +1836,11 @@ static void RB_StencilShadowPass( const drawSurf_t* drawSurfs, const viewLight_t
{
qglDrawElementsBaseVertex( GL_TRIANGLES, r_singleTriangle.GetBool() ? 3 : drawSurf->numIndexes, GL_INDEX_TYPE, ( triIndex_t* )indexOffset, vertOffset / sizeof( idShadowVert ) );
}
// RB: added stats
backEnd.pc.c_shadowElements++;
backEnd.pc.c_shadowIndexes += drawSurf->numIndexes;
// RB end
}
}
@ -2266,6 +2280,7 @@ static int RB_DrawShaderPasses( const drawSurf_t* const* const drawSurfs, const
continue;
}
// see if we are a new-style stage
newShaderStage_t* newStage = pStage->newStage;
if( newStage != NULL )
@ -2285,7 +2300,7 @@ static int RB_DrawShaderPasses( const drawSurf_t* const* const drawSurfs, const
// RB: CRITICAL BUGFIX: changed newStage->glslProgram to vertexProgram and fragmentProgram
// otherwise it will result in an out of bounds crash in RB_DrawElementsWithCounters
renderProgManager.BindShader( newStage->vertexProgram, newStage->fragmentProgram );
renderProgManager.BindShader( newStage->glslProgram, newStage->vertexProgram, newStage->fragmentProgram, false );
// RB end
for( int j = 0; j < newStage->numVertexParms; j++ )

View file

@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2013-2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -328,11 +329,13 @@ R_SetupDrawSurfJoints
*/
void R_SetupDrawSurfJoints( drawSurf_t* drawSurf, const srfTriangles_t* tri, const idMaterial* shader )
{
if( tri->staticModelWithJoints == NULL || !r_useGPUSkinning.GetBool() )
// RB: added check wether GPU skinning is available at all
if( tri->staticModelWithJoints == NULL || !r_useGPUSkinning.GetBool() || !glConfig.gpuSkinningAvailable )
{
drawSurf->jointCache = 0;
return;
}
// RB end
idRenderModelStatic* model = tri->staticModelWithJoints;
assert( model->jointsInverted != NULL );
@ -666,7 +669,10 @@ void R_AddSingleModel( viewEntity_t* vEntity )
// If the entire model wasn't visible, there is no need to check the
// individual surfaces.
const bool surfaceDirectlyVisible = modelIsVisible && !idRenderMatrix::CullBoundsToMVP( vEntity->mvp, tri->bounds );
const bool gpuSkinned = ( tri->staticModelWithJoints != NULL && r_useGPUSkinning.GetBool() );
// RB: added check wether GPU skinning is available at all
const bool gpuSkinned = ( tri->staticModelWithJoints != NULL && r_useGPUSkinning.GetBool() && glConfig.gpuSkinningAvailable );
// RB end
//--------------------------
// base drawing surface

View file

@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -84,7 +85,9 @@ static drawSurf_t* R_AutospriteDeform( drawSurf_t* surf )
return NULL;
}
const idJointMat* joints = ( srcTri->staticModelWithJoints != NULL && r_useGPUSkinning.GetBool() ) ? srcTri->staticModelWithJoints->jointsInverted : NULL;
// RB: added check wether GPU skinning is available at all
const idJointMat* joints = ( srcTri->staticModelWithJoints != NULL && r_useGPUSkinning.GetBool() && glConfig.gpuSkinningAvailable ) ? srcTri->staticModelWithJoints->jointsInverted : NULL;
// RB end
idVec3 leftDir;
idVec3 upDir;
@ -179,7 +182,9 @@ static drawSurf_t* R_TubeDeform( drawSurf_t* surf )
common->Error( "R_TubeDeform: autosprite had odd index count" );
}
const idJointMat* joints = ( srcTri->staticModelWithJoints != NULL && r_useGPUSkinning.GetBool() ) ? srcTri->staticModelWithJoints->jointsInverted : NULL;
// RB: added check wether GPU skinning is available at all
const idJointMat* joints = ( srcTri->staticModelWithJoints != NULL && r_useGPUSkinning.GetBool() && glConfig.gpuSkinningAvailable ) ? srcTri->staticModelWithJoints->jointsInverted : NULL;
// RB end
// we need the view direction to project the minor axis of the tube
// as the view changes
@ -649,7 +654,9 @@ static void AddTriangleToIsland_r( const srfTriangles_t* tri, int triangleNum, b
island->tris[island->numTris] = triangleNum;
island->numTris++;
const idJointMat* joints = ( tri->staticModelWithJoints != NULL && r_useGPUSkinning.GetBool() ) ? tri->staticModelWithJoints->jointsInverted : NULL;
// RB: added check wether GPU skinning is available at all
const idJointMat* joints = ( tri->staticModelWithJoints != NULL && r_useGPUSkinning.GetBool() && glConfig.gpuSkinningAvailable ) ? tri->staticModelWithJoints->jointsInverted : NULL;
// RB end
// recurse into all neighbors
const int a = tri->indexes[triangleNum * 3 + 0];
@ -737,7 +744,9 @@ static drawSurf_t* R_EyeballDeform( drawSurf_t* surf )
return NULL;
}
const idJointMat* joints = ( srcTri->staticModelWithJoints != NULL && r_useGPUSkinning.GetBool() ) ? srcTri->staticModelWithJoints->jointsInverted : NULL;
// RB: added check wether GPU skinning is available at all
const idJointMat* joints = ( srcTri->staticModelWithJoints != NULL && r_useGPUSkinning.GetBool() && glConfig.gpuSkinningAvailable ) ? srcTri->staticModelWithJoints->jointsInverted : NULL;
// RB end
// the srfTriangles_t are in frame memory and will be automatically disposed of
srfTriangles_t* newTri = ( srfTriangles_t* )R_ClearedFrameAlloc( sizeof( *newTri ), FRAME_ALLOC_SURFACE_TRIANGLES );
@ -868,7 +877,9 @@ static drawSurf_t* R_ParticleDeform( drawSurf_t* surf, bool useArea )
float totalArea = 0.0f;
float* sourceTriAreas = NULL;
const idJointMat* joints = ( ( srcTri->staticModelWithJoints != NULL ) && r_useGPUSkinning.GetBool() ) ? srcTri->staticModelWithJoints->jointsInverted : NULL;
// RB: added check wether GPU skinning is available at all
const idJointMat* joints = ( ( srcTri->staticModelWithJoints != NULL ) && r_useGPUSkinning.GetBool() && glConfig.gpuSkinningAvailable ) ? srcTri->staticModelWithJoints->jointsInverted : NULL;
// RB end
if( useArea )
{

View file

@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -68,7 +69,10 @@ void R_SurfaceToTextureAxis( const srfTriangles_t* tri, idVec3& origin, idVec3 a
const idVec2 boundsOrg( floor( ( boundsMin.x + boundsMax.x ) * 0.5f ), floor( ( boundsMin.y + boundsMax.y ) * 0.5f ) );
// determine the world S and T vectors from the first drawSurf triangle
const idJointMat* joints = ( tri->staticModelWithJoints != NULL && r_useGPUSkinning.GetBool() ) ? tri->staticModelWithJoints->jointsInverted : NULL;
// RB: added check wether GPU skinning is available at all
const idJointMat* joints = ( tri->staticModelWithJoints != NULL && r_useGPUSkinning.GetBool() && glConfig.gpuSkinningAvailable ) ? tri->staticModelWithJoints->jointsInverted : NULL;
// RB end
const idVec3 aXYZ = idDrawVert::GetSkinnedDrawVertPosition( tri->verts[ tri->indexes[0] ], joints );
const idVec3 bXYZ = idDrawVert::GetSkinnedDrawVertPosition( tri->verts[ tri->indexes[1] ], joints );

View file

@ -3,6 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -119,7 +120,9 @@ bool R_PreciseCullSurface( const drawSurf_t* drawSurf, idBounds& ndcBounds )
// get an exact bounds of the triangles for scissor cropping
ndcBounds.Clear();
const idJointMat* joints = ( tri->staticModelWithJoints != NULL && r_useGPUSkinning.GetBool() ) ? tri->staticModelWithJoints->jointsInverted : NULL;
// RB: added check wether GPU skinning is available at all
const idJointMat* joints = ( tri->staticModelWithJoints != NULL && r_useGPUSkinning.GetBool() && glConfig.gpuSkinningAvailable ) ? tri->staticModelWithJoints->jointsInverted : NULL;
// RB end
for( int i = 0; i < tri->numVerts; i++ )
{

View file

@ -3,7 +3,7 @@
Doom 3 BFG Edition GPL Source Code
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
Copyright (C) 2013 Robert Beckebans
Copyright (C) 2013-2014 Robert Beckebans
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
@ -619,7 +619,10 @@ localTrace_t R_LocalTrace( const idVec3& start, const idVec3& end, const float r
byte* cullBits = ( byte* ) _alloca16( ALIGN( tri->numVerts, 4 ) ); // round up to a multiple of 4 for SIMD
byte totalOr = 0;
const idJointMat* joints = ( tri->staticModelWithJoints != NULL && r_useGPUSkinning.GetBool() ) ? tri->staticModelWithJoints->jointsInverted : NULL;
// RB: added check wether GPU skinning is available at all
const idJointMat* joints = ( tri->staticModelWithJoints != NULL && r_useGPUSkinning.GetBool() && glConfig.gpuSkinningAvailable ) ? tri->staticModelWithJoints->jointsInverted : NULL;
// RB end
if( joints != NULL )
{
R_TracePointCullSkinned( cullBits, totalOr, radius, planes, tri->verts, tri->numVerts, joints );

View file

@ -390,6 +390,20 @@ static HGLRC CreateOpenGLContextOnDC( const HDC hdc, const bool debugContext )
if( m_hrc != NULL )
{
idLib::Printf( "created OpenGL %d.%d context\n", glMajorVersion, glMinorVersion );
if( useOpenGL32 == 2 )
{
glConfig.driverType = GLDRV_OPENGL32_CORE_PROFILE;
}
else if( useOpenGL32 == 1 )
{
glConfig.driverType = GLDRV_OPENGL32_COMPATIBILITY_PROFILE;
}
else
{
glConfig.driverType = GLDRV_OPENGL3X;
}
break;
}