2018-10-13 12:42:30 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 BFG Edition GPL Source Code
Copyright ( C ) 1993 - 2012 id Software LLC , a ZeniMax Media company .
Copyright ( C ) 2013 - 2018 Robert Beckebans
Copyright ( C ) 2016 - 2017 Dustin Land
This file is part of the Doom 3 BFG Edition GPL Source Code ( " Doom 3 BFG Edition Source Code " ) .
Doom 3 BFG Edition Source Code is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code . If not , see < http : //www.gnu.org/licenses/>.
In addition , the Doom 3 BFG Edition Source Code is also subject to certain additional terms . You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code . If not , please request a copy in writing from id Software at the address below .
If you have questions concerning this license or the applicable additional terms , you may contact in writing id Software LLC , c / o ZeniMax Media Inc . , Suite 120 , Rockville , Maryland 20850 USA .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# pragma hdrstop
# include "precompiled.h"
# include "../RenderCommon.h"
2018-11-01 15:30:05 +00:00
idCVar r_displayGLSLCompilerMessages ( " r_displayGLSLCompilerMessages " , " 1 " , CVAR_BOOL | CVAR_ARCHIVE , " Show info messages the GPU driver outputs when compiling the shaders " ) ;
idCVar r_alwaysExportGLSL ( " r_alwaysExportGLSL " , " 1 " , CVAR_BOOL , " " ) ;
2018-10-13 12:42:30 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idRenderProgManager : : StartFrame
= = = = = = = = = = = = = = = = = = = = = = = =
*/
void idRenderProgManager : : StartFrame ( )
{
}
2018-10-28 12:22:36 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idRenderProgManager : : BindProgram
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
void idRenderProgManager : : BindProgram ( int index )
{
if ( current = = index )
{
return ;
}
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
current = index ;
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
RENDERLOG_PRINTF ( " Binding GLSL Program %s \n " , renderProgs [ index ] . name . c_str ( ) ) ;
glUseProgram ( renderProgs [ index ] . progId ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idRenderProgManager : : Unbind
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
void idRenderProgManager : : Unbind ( )
{
current = - 1 ;
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
glUseProgram ( 0 ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idRenderProgManager : : LoadShader
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
void idRenderProgManager : : LoadShader ( int index , rpStage_t stage )
{
if ( shaders [ index ] . progId ! = INVALID_PROGID )
{
return ; // Already loaded
}
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
LoadShader ( shaders [ index ] ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idRenderProgManager : : LoadGLSLShader
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
void idRenderProgManager : : LoadShader ( shader_t & shader )
{
idStr inFile ;
idStr outFileHLSL ;
idStr outFileGLSL ;
idStr outFileUniforms ;
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
// RB: replaced backslashes
inFile . Format ( " renderprogs/%s " , shader . name . c_str ( ) ) ;
inFile . StripFileExtension ( ) ;
outFileHLSL . Format ( " renderprogs/hlsl/%s%s " , shader . name . c_str ( ) , shader . nameOutSuffix . c_str ( ) ) ;
outFileHLSL . StripFileExtension ( ) ;
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
switch ( glConfig . driverType )
{
case GLDRV_OPENGL_MESA :
{
outFileGLSL . Format ( " renderprogs/glsles-3_00/%s%s " , shader . name . c_str ( ) , shader . nameOutSuffix . c_str ( ) ) ;
outFileUniforms . Format ( " renderprogs/glsles-3_00/%s%s " , shader . name . c_str ( ) , shader . nameOutSuffix . c_str ( ) ) ;
break ;
}
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
case GLDRV_VULKAN :
{
outFileGLSL . Format ( " renderprogs/vkglsl/%s%s " , shader . name . c_str ( ) , shader . nameOutSuffix . c_str ( ) ) ;
outFileUniforms . Format ( " renderprogs/vkglsl/%s%s " , shader . name . c_str ( ) , shader . nameOutSuffix . c_str ( ) ) ;
break ;
}
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
default :
{
2021-04-29 13:20:45 +00:00
//SRS - OSX supports only up to GLSL 4.1
# if defined(__APPLE__)
2021-04-19 18:31:15 +00:00
outFileGLSL . Format ( " renderprogs/glsl-4_10/%s%s " , shader . name . c_str ( ) , shader . nameOutSuffix . c_str ( ) ) ;
outFileUniforms . Format ( " renderprogs/glsl-4_10/%s%s " , shader . name . c_str ( ) , shader . nameOutSuffix . c_str ( ) ) ;
2021-04-29 13:20:45 +00:00
# else
outFileGLSL . Format ( " renderprogs/glsl-4_50/%s%s " , shader . name . c_str ( ) , shader . nameOutSuffix . c_str ( ) ) ;
outFileUniforms . Format ( " renderprogs/glsl-4_50/%s%s " , shader . name . c_str ( ) , shader . nameOutSuffix . c_str ( ) ) ;
# endif
2018-10-28 12:22:36 +00:00
}
}
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
outFileGLSL . StripFileExtension ( ) ;
outFileUniforms . StripFileExtension ( ) ;
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
GLenum glTarget ;
if ( shader . stage = = SHADER_STAGE_FRAGMENT )
{
glTarget = GL_FRAGMENT_SHADER ;
inFile + = " .ps.hlsl " ;
outFileHLSL + = " .ps.hlsl " ;
outFileGLSL + = " .frag " ;
outFileUniforms + = " .frag.layout " ;
}
else
{
glTarget = GL_VERTEX_SHADER ;
inFile + = " .vs.hlsl " ;
outFileHLSL + = " .vs.hlsl " ;
outFileGLSL + = " .vert " ;
outFileUniforms + = " .vert.layout " ;
}
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
// first check whether we already have a valid GLSL file and compare it to the hlsl timestamp;
ID_TIME_T hlslTimeStamp ;
int hlslFileLength = fileSystem - > ReadFile ( inFile . c_str ( ) , NULL , & hlslTimeStamp ) ;
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
ID_TIME_T glslTimeStamp ;
int glslFileLength = fileSystem - > ReadFile ( outFileGLSL . c_str ( ) , NULL , & glslTimeStamp ) ;
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
// 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 ! = FILE_NOT_FOUND_TIMESTAMP & & hlslTimeStamp > glslTimeStamp ) | | r_alwaysExportGLSL . GetBool ( ) )
{
const char * hlslFileBuffer = NULL ;
int len = 0 ;
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
if ( hlslFileLength < = 0 )
{
// hlsl file doesn't even exist bail out
hlslFileBuffer = FindEmbeddedSourceShader ( inFile . c_str ( ) ) ;
if ( hlslFileBuffer = = NULL )
{
return ;
}
len = strlen ( hlslFileBuffer ) ;
}
else
{
len = fileSystem - > ReadFile ( inFile . c_str ( ) , ( void * * ) & hlslFileBuffer ) ;
}
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
if ( len < = 0 )
{
return ;
}
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
idStrList compileMacros ;
for ( int j = 0 ; j < MAX_SHADER_MACRO_NAMES ; j + + )
{
if ( BIT ( j ) & shader . shaderFeatures )
{
const char * macroName = GetGLSLMacroName ( ( shaderFeature_t ) j ) ;
compileMacros . Append ( idStr ( macroName ) ) ;
}
}
2019-11-11 19:27:44 +00:00
2019-10-04 09:56:37 +00:00
// 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
bool hasGPUSkinning = false ;
2019-11-11 19:27:44 +00:00
2019-10-04 09:56:37 +00:00
if ( idStr : : Icmp ( shader . name . c_str ( ) , " heatHaze " ) = = 0 | |
idStr : : Icmp ( shader . name . c_str ( ) , " heatHazeWithMask " ) = = 0 | |
idStr : : Icmp ( shader . name . c_str ( ) , " heatHazeWithMaskAndVertex " ) = = 0 | |
( BIT ( USE_GPU_SKINNING ) & shader . shaderFeatures ) )
{
hasGPUSkinning = true ;
}
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
idStr hlslCode ( hlslFileBuffer ) ;
idStr programHLSL = StripDeadCode ( hlslCode , inFile , compileMacros , shader . builtin ) ;
2019-11-22 17:25:33 +00:00
programGLSL = ConvertCG2GLSL ( programHLSL , inFile . c_str ( ) , shader . stage , programUniforms , false , hasGPUSkinning , shader . vertexLayout ) ;
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
fileSystem - > WriteFile ( outFileHLSL , programHLSL . c_str ( ) , programHLSL . Length ( ) , " fs_savepath " ) ;
fileSystem - > WriteFile ( outFileGLSL , programGLSL . c_str ( ) , programGLSL . Length ( ) , " fs_savepath " ) ;
fileSystem - > WriteFile ( outFileUniforms , programUniforms . c_str ( ) , programUniforms . Length ( ) , " fs_savepath " ) ;
}
else
{
// read in the glsl file
void * fileBufferGLSL = NULL ;
int lengthGLSL = fileSystem - > ReadFile ( outFileGLSL . c_str ( ) , & fileBufferGLSL ) ;
if ( lengthGLSL < = 0 )
{
idLib : : Error ( " GLSL file %s could not be loaded and may be corrupt " , outFileGLSL . c_str ( ) ) ;
}
programGLSL = ( const char * ) fileBufferGLSL ;
Mem_Free ( fileBufferGLSL ) ;
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
{
// read in the uniform file
void * fileBufferUniforms = NULL ;
int lengthUniforms = fileSystem - > ReadFile ( outFileUniforms . c_str ( ) , & fileBufferUniforms ) ;
if ( lengthUniforms < = 0 )
{
idLib : : Error ( " uniform file %s could not be loaded and may be corrupt " , outFileUniforms . c_str ( ) ) ;
}
programUniforms = ( const char * ) fileBufferUniforms ;
Mem_Free ( fileBufferUniforms ) ;
}
}
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
// RB: find the uniforms locations in either the vertex or fragment uniform array
// this uses the new layout structure
{
shader . uniforms . Clear ( ) ;
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
idLexer src ( programUniforms , programUniforms . Length ( ) , " uniforms " ) ;
idToken token ;
if ( src . ExpectTokenString ( " uniforms " ) )
{
src . ExpectTokenString ( " [ " ) ;
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
while ( ! src . CheckTokenString ( " ] " ) )
{
src . ReadToken ( & token ) ;
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
int index = - 1 ;
for ( int i = 0 ; i < RENDERPARM_TOTAL & & index = = - 1 ; i + + )
{
const char * parmName = GetGLSLParmName ( i ) ;
if ( token = = parmName )
{
index = i ;
}
}
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
if ( index = = - 1 )
{
idLib : : Error ( " couldn't find uniform %s for %s " , token . c_str ( ) , outFileGLSL . c_str ( ) ) ;
}
shader . uniforms . Append ( index ) ;
}
}
}
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
// create and compile the shader
shader . progId = glCreateShader ( glTarget ) ;
if ( shader . progId )
{
const char * source [ 1 ] = { programGLSL . c_str ( ) } ;
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
glShaderSource ( shader . progId , 1 , source , NULL ) ;
glCompileShader ( shader . progId ) ;
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
int infologLength = 0 ;
glGetShaderiv ( shader . progId , GL_INFO_LOG_LENGTH , & infologLength ) ;
if ( infologLength > 1 )
{
idTempArray < char > infoLog ( infologLength ) ;
int charsWritten = 0 ;
glGetShaderInfoLog ( shader . progId , infologLength , & charsWritten , infoLog . Ptr ( ) ) ;
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
// catch the strings the ATI and Intel drivers output on success
if ( strstr ( infoLog . Ptr ( ) , " successfully compiled to run on hardware " ) ! = NULL | |
strstr ( infoLog . Ptr ( ) , " No errors. " ) ! = NULL )
{
//idLib::Printf( "%s program %s from %s compiled to run on hardware\n", typeName, GetName(), GetFileName() );
}
else if ( r_displayGLSLCompilerMessages . GetBool ( ) ) // DG: check for the CVar I added above
{
idLib : : Printf ( " While compiling %s program %s \n " , ( shader . stage = = SHADER_STAGE_FRAGMENT ) ? " fragment " : " vertex " , inFile . c_str ( ) ) ;
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
const char separator = ' \n ' ;
idList < idStr > lines ;
lines . Clear ( ) ;
idStr source ( programGLSL ) ;
lines . Append ( source ) ;
for ( int index = 0 , ofs = lines [ index ] . Find ( separator ) ; ofs ! = - 1 ; index + + , ofs = lines [ index ] . Find ( separator ) )
{
lines . Append ( lines [ index ] . c_str ( ) + ofs + 1 ) ;
lines [ index ] . CapLength ( ofs ) ;
}
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
idLib : : Printf ( " ----------------- \n " ) ;
for ( int i = 0 ; i < lines . Num ( ) ; i + + )
{
idLib : : Printf ( " %3d: %s \n " , i + 1 , lines [ i ] . c_str ( ) ) ;
}
idLib : : Printf ( " ----------------- \n " ) ;
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
idLib : : Printf ( " %s \n " , infoLog . Ptr ( ) ) ;
}
}
2019-11-11 19:27:44 +00:00
2018-10-28 12:22:36 +00:00
GLint compiled = GL_FALSE ;
glGetShaderiv ( shader . progId , GL_COMPILE_STATUS , & compiled ) ;
if ( compiled = = GL_FALSE )
{
glDeleteShader ( shader . progId ) ;
return ;
}
}
}
2018-10-13 16:34:29 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idRenderProgManager : : LoadGLSLProgram
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
void idRenderProgManager : : LoadGLSLProgram ( const int programIndex , const int vertexShaderIndex , const int fragmentShaderIndex )
{
renderProg_t & prog = renderProgs [ programIndex ] ;
2019-11-11 19:27:44 +00:00
2018-10-13 16:34:29 +00:00
if ( prog . progId ! = INVALID_PROGID )
{
return ; // Already loaded
}
2019-11-11 19:27:44 +00:00
2018-10-13 16:34:29 +00:00
//shader_t& vertexShader = shaders[ vertexShaderIndex ];
//shader_t& fragmentShader = shaders[ fragmentShaderIndex ];
2019-11-11 19:27:44 +00:00
2018-10-13 16:34:29 +00:00
GLuint vertexProgID = ( vertexShaderIndex ! = - 1 ) ? shaders [ vertexShaderIndex ] . progId : INVALID_PROGID ;
GLuint fragmentProgID = ( fragmentShaderIndex ! = - 1 ) ? shaders [ fragmentShaderIndex ] . progId : INVALID_PROGID ;
2019-11-11 19:27:44 +00:00
2018-10-13 16:34:29 +00:00
const GLuint program = glCreateProgram ( ) ;
if ( program )
{
if ( vertexProgID ! = INVALID_PROGID )
{
glAttachShader ( program , vertexProgID ) ;
}
2019-11-11 19:27:44 +00:00
2018-10-13 16:34:29 +00:00
if ( fragmentProgID ! = INVALID_PROGID )
{
glAttachShader ( program , fragmentProgID ) ;
}
2019-11-11 19:27:44 +00:00
2018-10-13 16:34:29 +00:00
// bind vertex attribute locations
for ( int i = 0 ; attribsPC [ i ] . glsl ! = NULL ; i + + )
{
if ( ( attribsPC [ i ] . flags & AT_VS_IN ) ! = 0 )
{
glBindAttribLocation ( program , attribsPC [ i ] . bind , attribsPC [ i ] . glsl ) ;
}
}
2019-11-11 19:27:44 +00:00
2018-10-13 16:34:29 +00:00
glLinkProgram ( program ) ;
2019-11-11 19:27:44 +00:00
2018-10-13 16:34:29 +00:00
int infologLength = 0 ;
glGetProgramiv ( program , GL_INFO_LOG_LENGTH , & infologLength ) ;
if ( infologLength > 1 )
{
char * infoLog = ( char * ) malloc ( infologLength ) ;
int charsWritten = 0 ;
glGetProgramInfoLog ( program , infologLength , & charsWritten , infoLog ) ;
2019-11-11 19:27:44 +00:00
2018-10-13 16:34:29 +00:00
// catch the strings the ATI and Intel drivers output on success
if ( strstr ( infoLog , " Vertex shader(s) linked, fragment shader(s) linked. " ) ! = NULL | | strstr ( infoLog , " No errors. " ) ! = NULL )
{
//idLib::Printf( "render prog %s from %s linked\n", GetName(), GetFileName() );
}
else
{
idLib : : Printf ( " While linking GLSL program %d with vertexShader %s and fragmentShader %s \n " ,
programIndex ,
( vertexShaderIndex > = 0 ) ? shaders [ vertexShaderIndex ] . name . c_str ( ) : " <Invalid> " ,
( fragmentShaderIndex > = 0 ) ? shaders [ fragmentShaderIndex ] . name . c_str ( ) : " <Invalid> " ) ;
idLib : : Printf ( " %s \n " , infoLog ) ;
}
2019-11-11 19:27:44 +00:00
2018-10-13 16:34:29 +00:00
free ( infoLog ) ;
}
}
2019-11-11 19:27:44 +00:00
2018-10-13 16:34:29 +00:00
int linked = GL_FALSE ;
glGetProgramiv ( program , GL_LINK_STATUS , & linked ) ;
if ( linked = = GL_FALSE )
{
glDeleteProgram ( program ) ;
idLib : : Error ( " While linking GLSL program %d with vertexShader %s and fragmentShader %s \n " ,
programIndex ,
( vertexShaderIndex > = 0 ) ? shaders [ vertexShaderIndex ] . name . c_str ( ) : " <Invalid> " ,
( fragmentShaderIndex > = 0 ) ? shaders [ fragmentShaderIndex ] . name . c_str ( ) : " <Invalid> " ) ;
return ;
}
2019-11-11 19:27:44 +00:00
2018-10-13 16:34:29 +00:00
//shaders[ vertexShaderIndex ].uniformArray = glGetUniformLocation( program, VERTEX_UNIFORM_ARRAY_NAME );
//shaders[ fragmentShaderIndex ].uniformArray = glGetUniformLocation( program, FRAGMENT_UNIFORM_ARRAY_NAME );
2019-11-11 19:27:44 +00:00
2018-10-13 16:34:29 +00:00
if ( vertexShaderIndex > - 1 & & shaders [ vertexShaderIndex ] . uniforms . Num ( ) > 0 )
{
shader_t & vertexShader = shaders [ vertexShaderIndex ] ;
vertexShader . uniformArray = glGetUniformLocation ( program , VERTEX_UNIFORM_ARRAY_NAME ) ;
}
2019-11-11 19:27:44 +00:00
2018-10-13 16:34:29 +00:00
if ( fragmentShaderIndex > - 1 & & shaders [ fragmentShaderIndex ] . uniforms . Num ( ) > 0 )
{
shader_t & fragmentShader = shaders [ fragmentShaderIndex ] ;
fragmentShader . uniformArray = glGetUniformLocation ( program , FRAGMENT_UNIFORM_ARRAY_NAME ) ;
}
2019-11-11 19:27:44 +00:00
2018-10-13 16:34:29 +00:00
assert ( shaders [ vertexShaderIndex ] . uniformArray ! = - 1 | | vertexShaderIndex > - 1 | | shaders [ vertexShaderIndex ] . uniforms . Num ( ) = = 0 ) ;
assert ( shaders [ fragmentShaderIndex ] . uniformArray ! = - 1 | | fragmentShaderIndex > - 1 | | shaders [ fragmentShaderIndex ] . uniforms . Num ( ) = = 0 ) ;
2019-11-11 19:27:44 +00:00
2018-10-13 16:34:29 +00:00
// RB: only load joint uniform buffers if available
if ( glConfig . gpuSkinningAvailable )
{
// get the uniform buffer binding for skinning joint matrices
GLint blockIndex = glGetUniformBlockIndex ( program , " matrices_ubo " ) ;
if ( blockIndex ! = - 1 )
{
glUniformBlockBinding ( program , blockIndex , 0 ) ;
}
}
// RB end
2019-11-11 19:27:44 +00:00
2018-10-13 16:34:29 +00:00
// set the texture unit locations once for the render program. We only need to do this once since we only link the program once
glUseProgram ( program ) ;
int numSamplerUniforms = 0 ;
for ( int i = 0 ; i < MAX_PROG_TEXTURE_PARMS ; + + i )
{
GLint loc = glGetUniformLocation ( program , va ( " samp%d " , i ) ) ;
if ( loc ! = - 1 )
{
glUniform1i ( loc , i ) ;
numSamplerUniforms + + ;
}
}
2019-11-11 19:27:44 +00:00
2018-10-13 16:34:29 +00:00
idStr programName = shaders [ vertexShaderIndex ] . name ;
programName . StripFileExtension ( ) ;
prog . name = programName ;
prog . progId = program ;
prog . fragmentShaderIndex = fragmentShaderIndex ;
prog . vertexShaderIndex = vertexShaderIndex ;
2019-11-11 19:27:44 +00:00
2018-10-13 16:34:29 +00:00
// RB: removed idStr::Icmp( name, "heatHaze.vfp" ) == 0 hack
// this requires r_useUniformArrays 1
for ( int i = 0 ; i < shaders [ vertexShaderIndex ] . uniforms . Num ( ) ; i + + )
{
if ( shaders [ vertexShaderIndex ] . uniforms [ i ] = = RENDERPARM_ENABLE_SKINNING )
{
prog . usesJoints = true ;
prog . optionalSkinning = true ;
}
}
// RB end
}
2018-10-28 12:22:36 +00:00
2018-10-13 12:42:30 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idRenderProgManager : : CommitUnforms
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
void idRenderProgManager : : CommitUniforms ( uint64 stateBits )
{
2018-10-13 16:34:29 +00:00
const int progID = current ;
const renderProg_t & prog = renderProgs [ progID ] ;
2019-11-11 19:27:44 +00:00
2018-10-13 12:42:30 +00:00
//GL_CheckErrors();
2019-11-11 19:27:44 +00:00
2018-10-13 12:42:30 +00:00
ALIGNTYPE16 idVec4 localVectors [ RENDERPARM_TOTAL ] ;
2019-11-11 19:27:44 +00:00
2018-10-13 16:34:29 +00:00
auto commitarray = [ & ] ( idVec4 ( & vectors ) [ RENDERPARM_TOTAL ] , shader_t & shader )
2018-10-13 12:42:30 +00:00
{
2018-10-13 16:34:29 +00:00
const int numUniforms = shader . uniforms . Num ( ) ;
if ( shader . uniformArray ! = - 1 & & numUniforms > 0 )
2018-10-13 12:42:30 +00:00
{
int totalUniforms = 0 ;
2018-10-13 16:34:29 +00:00
for ( int i = 0 ; i < numUniforms ; + + i )
2018-10-13 12:42:30 +00:00
{
// RB: HACK rpShadowMatrices[6 * 4]
2018-10-13 16:34:29 +00:00
if ( shader . uniforms [ i ] = = RENDERPARM_SHADOW_MATRIX_0_X )
2018-10-13 12:42:30 +00:00
{
for ( int j = 0 ; j < ( 6 * 4 ) ; j + + )
{
2018-10-13 16:34:29 +00:00
vectors [ i + j ] = uniforms [ shader . uniforms [ i ] + j ] ;
2018-10-13 12:42:30 +00:00
totalUniforms + + ;
}
2019-11-11 19:27:44 +00:00
2018-10-13 12:42:30 +00:00
}
else
{
2018-10-13 16:34:29 +00:00
vectors [ i ] = uniforms [ shader . uniforms [ i ] ] ;
2018-10-13 12:42:30 +00:00
totalUniforms + + ;
}
}
2018-10-13 16:34:29 +00:00
glUniform4fv ( shader . uniformArray , totalUniforms , localVectors - > ToFloatPtr ( ) ) ;
2018-10-13 12:42:30 +00:00
}
2018-10-13 16:34:29 +00:00
} ;
2019-11-11 19:27:44 +00:00
2018-10-13 16:34:29 +00:00
if ( prog . vertexShaderIndex > = 0 )
{
commitarray ( localVectors , shaders [ prog . vertexShaderIndex ] ) ;
2018-10-13 12:42:30 +00:00
}
2019-11-11 19:27:44 +00:00
2018-10-13 12:42:30 +00:00
if ( prog . fragmentShaderIndex > = 0 )
{
2018-10-13 16:34:29 +00:00
commitarray ( localVectors , shaders [ prog . fragmentShaderIndex ] ) ;
2018-10-13 12:42:30 +00:00
}
2019-11-11 19:27:44 +00:00
2018-10-13 12:42:30 +00:00
//GL_CheckErrors();
}
2018-11-03 11:01:03 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
idRenderProgManager : : KillAllShaders ( )
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
void idRenderProgManager : : KillAllShaders ( )
{
Unbind ( ) ;
2019-11-11 19:27:44 +00:00
2018-11-03 11:01:03 +00:00
for ( int i = 0 ; i < shaders . Num ( ) ; i + + )
{
if ( shaders [ i ] . progId ! = INVALID_PROGID )
{
glDeleteShader ( shaders [ i ] . progId ) ;
shaders [ i ] . progId = INVALID_PROGID ;
}
}
2019-11-11 19:27:44 +00:00
2018-11-03 11:01:03 +00:00
for ( int i = 0 ; i < renderProgs . Num ( ) ; + + i )
{
if ( renderProgs [ i ] . progId ! = INVALID_PROGID )
{
glDeleteProgram ( renderProgs [ i ] . progId ) ;
renderProgs [ i ] . progId = INVALID_PROGID ;
}
}
}
2018-10-13 12:42:30 +00:00
2018-11-03 11:01:03 +00:00
/*
= = = = = = = = = = = = = = = = = = = =
idRenderBackend : : ResizeImages
= = = = = = = = = = = = = = = = = = = =
*/
void idRenderBackend : : ResizeImages ( )
{
// TODO resize framebuffers here
2019-10-04 09:56:37 +00:00
}