From cce21e0d76d99f40479ca50d07f55c99b11a457a Mon Sep 17 00:00:00 2001 From: RobertBeckebans Date: Sun, 20 Apr 2014 16:29:58 +0200 Subject: [PATCH] Added GLSL ES 1.0 backend for Mesa drivers #90 --- neo/renderer/GraphicsAPIWrapper.h | 11 +- neo/renderer/ModelOverlay.cpp | 7 +- neo/renderer/Model_md5.cpp | 5 +- neo/renderer/RenderProgs.cpp | 209 +++++++++---- neo/renderer/RenderProgs.h | 46 ++- neo/renderer/RenderProgs_GLSL.cpp | 399 ++++++++++++++++++++++--- neo/renderer/RenderSystem.h | 28 ++ neo/renderer/RenderSystem_init.cpp | 42 ++- neo/renderer/tr_backend_draw.cpp | 19 +- neo/renderer/tr_frontend_addmodels.cpp | 10 +- neo/renderer/tr_frontend_deform.cpp | 21 +- neo/renderer/tr_frontend_guisurf.cpp | 6 +- neo/renderer/tr_frontend_subview.cpp | 5 +- neo/renderer/tr_trace.cpp | 7 +- neo/sys/win32/win_glimp.cpp | 14 + 15 files changed, 693 insertions(+), 136 deletions(-) diff --git a/neo/renderer/GraphicsAPIWrapper.h b/neo/renderer/GraphicsAPIWrapper.h index 2cee9303..83894d0d 100644 --- a/neo/renderer/GraphicsAPIWrapper.h +++ b/neo/renderer/GraphicsAPIWrapper.h @@ -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(); diff --git a/neo/renderer/ModelOverlay.cpp b/neo/renderer/ModelOverlay.cpp index d2cf2569..fbea99b2 100644 --- a/neo/renderer/ModelOverlay.cpp +++ b/neo/renderer/ModelOverlay.cpp @@ -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 } diff --git a/neo/renderer/Model_md5.cpp b/neo/renderer/Model_md5.cpp index 6d132ded..69a6a530 100644 --- a/neo/renderer/Model_md5.cpp +++ b/neo/renderer/Model_md5.cpp @@ -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 ) { diff --git a/neo/renderer/RenderProgs.cpp b/neo/renderer/RenderProgs.cpp index 572518e5..aaa68188 100644 --- a/neo/renderer/RenderProgs.cpp +++ b/neo/renderer/RenderProgs.cpp @@ -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 diff --git a/neo/renderer/RenderProgs.h b/neo/renderer/RenderProgs.h index 098d7b03..1cf0c718 100644 --- a/neo/renderer/RenderProgs.h +++ b/neo/renderer/RenderProgs.h @@ -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 ); diff --git a/neo/renderer/RenderProgs_GLSL.cpp b/neo/renderer/RenderProgs_GLSL.cpp index fb515710..032ae789 100644 --- a/neo/renderer/RenderProgs_GLSL.cpp +++ b/neo/renderer/RenderProgs_GLSL.cpp @@ -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 ); diff --git a/neo/renderer/RenderSystem.h b/neo/renderer/RenderSystem.h index 224bc11d..95e3df1e 100644 --- a/neo/renderer/RenderSystem.h +++ b/neo/renderer/RenderSystem.h @@ -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 }; diff --git a/neo/renderer/RenderSystem_init.cpp b/neo/renderer/RenderSystem_init.cpp index f3af0381..8ba996dc 100644 --- a/neo/renderer/RenderSystem_init.cpp +++ b/neo/renderer/RenderSystem_init.cpp @@ -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" ); + } } /* diff --git a/neo/renderer/tr_backend_draw.cpp b/neo/renderer/tr_backend_draw.cpp index 9e277177..4202c2d1 100644 --- a/neo/renderer/tr_backend_draw.cpp +++ b/neo/renderer/tr_backend_draw.cpp @@ -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++ ) diff --git a/neo/renderer/tr_frontend_addmodels.cpp b/neo/renderer/tr_frontend_addmodels.cpp index 507f3612..bee04893 100644 --- a/neo/renderer/tr_frontend_addmodels.cpp +++ b/neo/renderer/tr_frontend_addmodels.cpp @@ -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 diff --git a/neo/renderer/tr_frontend_deform.cpp b/neo/renderer/tr_frontend_deform.cpp index f3da30a1..ed137581 100644 --- a/neo/renderer/tr_frontend_deform.cpp +++ b/neo/renderer/tr_frontend_deform.cpp @@ -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 ) { diff --git a/neo/renderer/tr_frontend_guisurf.cpp b/neo/renderer/tr_frontend_guisurf.cpp index cb619ca6..e7411945 100644 --- a/neo/renderer/tr_frontend_guisurf.cpp +++ b/neo/renderer/tr_frontend_guisurf.cpp @@ -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 ); diff --git a/neo/renderer/tr_frontend_subview.cpp b/neo/renderer/tr_frontend_subview.cpp index e0665f88..3ef7394d 100644 --- a/neo/renderer/tr_frontend_subview.cpp +++ b/neo/renderer/tr_frontend_subview.cpp @@ -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++ ) { diff --git a/neo/renderer/tr_trace.cpp b/neo/renderer/tr_trace.cpp index c4bffb4b..fd865b36 100644 --- a/neo/renderer/tr_trace.cpp +++ b/neo/renderer/tr_trace.cpp @@ -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 ); diff --git a/neo/sys/win32/win_glimp.cpp b/neo/sys/win32/win_glimp.cpp index 1bd8dd65..bbfca680 100644 --- a/neo/sys/win32/win_glimp.cpp +++ b/neo/sys/win32/win_glimp.cpp @@ -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; }