diff --git a/src/engine/renderer/gl_shader.cpp b/src/engine/renderer/gl_shader.cpp index 6ef7a0a48b..fb51e75d6d 100644 --- a/src/engine/renderer/gl_shader.cpp +++ b/src/engine/renderer/gl_shader.cpp @@ -231,33 +231,64 @@ std::string GetShaderPath() GLShaderManager::~GLShaderManager() = default; -void GLShaderManager::freeAll() -{ +void GLShaderManager::FreeAll() { _shaders.clear(); - for ( GLint sh : _deformShaders ) - glDeleteShader( sh ); - - _deformShaders.clear(); + deformShaderCount = 0; _deformShaderLookup.clear(); + for ( const ShaderPipelineDescriptor& pipeline : shaderPipelineDescriptors ) { + if ( pipeline.id ) { + glDeleteProgramPipelines( 1, &pipeline.id ); + } + } + + shaderPipelineDescriptors.clear(); + + for ( const ShaderProgramDescriptor& program : shaderProgramDescriptors ) { + if ( program.id ) { + glDeleteProgram( program.id ); + } + + if ( program.uniformLocations ) { + Z_Free( program.uniformLocations ); + } + + if ( program.uniformBlockIndexes ) { + Z_Free( program.uniformBlockIndexes ); + } + + if ( program.uniformFirewall ) { + Z_Free( program.uniformFirewall ); + } + } + + shaderProgramDescriptors.clear(); + + for ( const ShaderDescriptor& shader : shaderDescriptors ) { + if ( shader.id ) { + glDeleteShader( shader.id ); + } + } + + shaderDescriptors.clear(); + while ( !_shaderBuildQueue.empty() ) { _shaderBuildQueue.pop(); } } -void GLShaderManager::UpdateShaderProgramUniformLocations( GLShader *shader, shaderProgram_t *shaderProgram ) const -{ +void GLShaderManager::UpdateShaderProgramUniformLocations( GLShader* shader, ShaderProgramDescriptor* shaderProgram ) const { size_t uniformSize = shader->_uniformStorageSize; size_t numUniforms = shader->_uniforms.size(); size_t numUniformBlocks = shader->_uniformBlocks.size(); // create buffer for storing uniform locations - shaderProgram->uniformLocations = ( GLint * ) Z_Malloc( sizeof( GLint ) * numUniforms ); + shaderProgram->uniformLocations = ( GLint* ) Z_Malloc( sizeof( GLint ) * numUniforms ); // create buffer for uniform firewall - shaderProgram->uniformFirewall = ( byte * ) Z_Malloc( uniformSize ); + shaderProgram->uniformFirewall = ( byte* ) Z_Malloc( uniformSize ); // update uniforms for (GLUniform *uniform : shader->_uniforms) @@ -267,7 +298,7 @@ void GLShaderManager::UpdateShaderProgramUniformLocations( GLShader *shader, sha if( glConfig2.uniformBufferObjectAvailable ) { // create buffer for storing uniform block indexes - shaderProgram->uniformBlockIndexes = ( GLuint * ) Z_Malloc( sizeof( GLuint ) * numUniformBlocks ); + shaderProgram->uniformBlockIndexes = ( GLuint* ) Z_Malloc( sizeof( GLuint ) * numUniformBlocks ); // update uniform blocks for (GLUniformBlock *uniformBlock : shader->_uniformBlocks) @@ -868,36 +899,39 @@ void GLShaderManager::GenerateWorldHeaders() { GLWorldHeader = GLHeader( "GLWorldHeader", GenWorldHeader(), this ); } -std::string GLShaderManager::BuildDeformShaderText( const std::string& steps ) -{ +std::string GLShaderManager::GetDeformShaderName( const int index ) { + if ( ( !tr.world && !tr.loadingMap.size() ) || !index ) { + return Str::Format( "deformVertexes_%i", index ); + } + + if ( !tr.world ) { + return Str::Format( "deformVertexes_%s_%i", tr.loadingMap, index ); + } + + return Str::Format( "deformVertexes_%s_%i", tr.world->baseName, index ); +} + +std::string GLShaderManager::BuildDeformShaderText( const std::string& steps ) { std::string shaderText; shaderText = steps + "\n"; + shaderText += GetShaderText( "deformVertexes_vp.glsl" ); - // We added a lot of stuff but if we do something bad - // in the GLSL shaders then we want the proper line - // so we have to reset the line counting. - shaderText += "#line 0\n"; - shaderText += GetShaderText("deformVertexes_vp.glsl"); return shaderText; } -int GLShaderManager::getDeformShaderIndex( deformStage_t *deforms, int numDeforms ) -{ +int GLShaderManager::GetDeformShaderIndex( deformStage_t *deforms, int numDeforms ) { std::string steps = BuildDeformSteps( deforms, numDeforms ); - int index = _deformShaderLookup[ steps ] - 1; + uint32_t index = _deformShaderLookup[steps]; - if( index < 0 ) - { - // compile new deform shader + if( !index ) { std::string shaderText = GLShaderManager::BuildDeformShaderText( steps ); - _deformShaders.push_back(CompileShader( "deformVertexes", - shaderText, - { &GLVersionDeclaration, - &GLVertexHeader }, - GL_VERTEX_SHADER ) ); - index = _deformShaders.size(); - _deformShaderLookup[ steps ] = index--; + index = deformShaderCount; + FindShader( GetDeformShaderName( index ), shaderText, GL_VERTEX_SHADER, + std::vector { &GLVersionDeclaration, &GLVertexHeader } ); + + deformShaderCount++; + _deformShaderLookup[steps] = deformShaderCount; } return index; @@ -940,102 +974,386 @@ static bool IsUnusedPermutation( const char *compileMacros ) return false; } -// returns whether something was really built (using a cached one counts) -bool GLShaderManager::buildPermutation( GLShader *shader, int macroIndex, int deformIndex ) -{ - std::string compileMacros; - size_t i = macroIndex + ( deformIndex << shader->_compileMacros.size() ); +void GLShaderManager::BuildShader( ShaderDescriptor* descriptor ) { + if ( descriptor->id ) { + return; + } - // program already exists - if ( i < shader->_shaderPrograms.size() && - shader->_shaderPrograms[ i ].program ) - { - return false; + const int start = Sys::Milliseconds(); + + const GLchar* text[1] = { descriptor->shaderSource.data() }; + GLint length[1] = { ( GLint ) descriptor->shaderSource.size() }; + + GLuint shader = glCreateShader( descriptor->type ); + GL_CheckErrors(); + + glShaderSource( shader, 1, text, length ); + glCompileShader( shader ); + + GL_CheckErrors(); + + GLint compiled; + glGetShaderiv( shader, GL_COMPILE_STATUS, &compiled ); + + if ( !compiled ) { + std::string log = GetInfoLog( shader ); + std::vector infoLog = ParseInfoLog( log ); + PrintShaderSource( descriptor->name, shader, infoLog ); + + Log::Warn( "Compile log:\n%s", log ); + + switch ( descriptor->type ) { + case GL_VERTEX_SHADER: + ThrowShaderError( Str::Format( "Couldn't compile vertex shader: %s", descriptor->name ) ); + case GL_FRAGMENT_SHADER: + ThrowShaderError( Str::Format( "Couldn't compile fragment shader: %s", descriptor->name ) ); + case GL_COMPUTE_SHADER: + ThrowShaderError( Str::Format( "Couldn't compile compute shader: %s", descriptor->name ) ); + default: + break; + } } - if ( !shader->GetCompileMacrosString( macroIndex, compileMacros ) ) - { - return false; + descriptor->id = shader; + + const int time = Sys::Milliseconds() - start; + compileTime += time; + compileCount++; + Log::Debug( "Compilation: %i", time ); +} + +void GLShaderManager::BuildShaderProgram( ShaderProgramDescriptor* descriptor ) { + if ( descriptor->id ) { + return; } - shader->BuildShaderCompileMacros( compileMacros ); + const int start = Sys::Milliseconds(); - if ( IsUnusedPermutation( compileMacros.c_str() ) ) - return false; + GLuint program = glCreateProgram(); + GL_CheckErrors(); - if ( i >= shader->_shaderPrograms.size() ) - shader->_shaderPrograms.resize( (deformIndex + 1) << shader->_compileMacros.size() ); + for ( const GLuint& shader : descriptor->shaders ) { + if ( shader ) { + glAttachShader( program, shader ); + } else { + break; + } + } + GL_CheckErrors(); - shaderProgram_t *shaderProgram = &shader->_shaderPrograms[ i ]; - shaderProgram->attribs = shader->_vertexAttribsRequired; // | _vertexAttribsOptional; + BindAttribLocations( program ); - if ( deformIndex > 0 ) - { - shaderProgram_t *baseShader = &shader->_shaderPrograms[ macroIndex ]; - if ( ( !baseShader->VS && shader->_hasVertexShader ) || ( !baseShader->FS && shader->_hasFragmentShader ) ) - CompileGPUShaders( shader, baseShader, compileMacros ); + if ( glConfig2.getProgramBinaryAvailable ) { + glProgramParameteri( program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE ); + } + + if ( glConfig2.separateShaderObjectsAvailable ) { + glProgramParameteri( program, GL_PROGRAM_SEPARABLE, GL_TRUE ); + } + + GLint linked; + glLinkProgram( program ); + + glGetProgramiv( program, GL_LINK_STATUS, &linked ); + + if ( !linked ) { + Log::Warn( "Link log:" ); + Log::Warn( GetInfoLog( program ) ); + ThrowShaderError( "Shader program failed to link!" ); + } + + descriptor->id = program; + + const int time = Sys::Milliseconds() - start; + linkTime += time; + linkCount++; + Log::Debug( "Program creation + linking: %i", time ); +} + +ShaderProgramDescriptor* GLShaderManager::FindShaderProgram( std::vector& shaders, GLShader* mainShader, + GLShader::UniformData* uniformData ) { + std::vector::iterator it = std::find_if( shaderProgramDescriptors.begin(), shaderProgramDescriptors.end(), + [&]( const ShaderProgramDescriptor& program ) { + for ( const ShaderEntry& shader : shaders ) { + if ( std::find( program.shaderNames, program.shaderNames + program.shaderCount, shader ) + == program.shaderNames + program.shaderCount ) { + return false; + } + } - shaderProgram->program = glCreateProgram(); - if ( shader->_hasVertexShader ) { - glAttachShader( shaderProgram->program, baseShader->VS ); - glAttachShader( shaderProgram->program, _deformShaders[deformIndex] ); + return true; } - if ( shader->_hasFragmentShader ) { - glAttachShader( shaderProgram->program, baseShader->FS ); + ); + + if ( it == shaderProgramDescriptors.end() ) { + std::sort( shaders.begin(), shaders.end(), + []( const ShaderEntry& lhs, const ShaderEntry& rhs ) { + return lhs.name < rhs.name; + } + ); + + ShaderProgramDescriptor desc; + std::string combinedShaderText; + std::vector buildQueue; + buildQueue.reserve( shaders.size() ); + + for ( const ShaderEntry& shader : shaders ) { + std::vector::iterator shaderIt = std::find_if( shaderDescriptors.begin(), shaderDescriptors.end(), + [&]( const ShaderDescriptor& other ) { + return shader.type == other.type && shader.macro == other.macro && shader.name == other.name; + } + ); + + if ( shaderIt == shaderDescriptors.end() ) { + ThrowShaderError( Str::Format( "Shader not found: %s %u", shader.name, shader.macro ) ); + } + + buildQueue.emplace_back( &*shaderIt ); + + combinedShaderText += shaderIt->shaderSource; + } + + desc.checkSum = Com_BlockChecksum( combinedShaderText.c_str(), combinedShaderText.length() ); + + if ( !LoadShaderBinary( shaders, mainShader->_name, &desc ) ) { + for ( ShaderDescriptor* shader : buildQueue ) { + BuildShader( shader ); + desc.AttachShader( &*shader ); + } + BuildShaderProgram( &desc ); + SaveShaderBinary( &desc ); } - BindAttribLocations( shaderProgram->program ); - LinkProgram( shaderProgram->program ); + UpdateShaderProgramUniformLocations( mainShader, &desc ); + uniformData->uniformLocations = desc.uniformLocations; + uniformData->uniformBlockIndexes = desc.uniformBlockIndexes; + uniformData->uniformFirewall = desc.uniformFirewall; + GL_BindProgram( desc.id, true ); + mainShader->SetShaderProgramUniforms( &desc ); + GL_BindNullProgram( true ); + + shaderProgramDescriptors.emplace_back( desc ); + + return &shaderProgramDescriptors[shaderProgramDescriptors.size() - 1]; } - else if ( !LoadShaderBinary( shader, i ) ) - { - CompileAndLinkGPUShaderProgram( shader, shaderProgram, compileMacros, deformIndex ); - SaveShaderBinary( shader, i ); + + return &*it; +} + +ShaderPipelineDescriptor* GLShaderManager::FindShaderPipelines( + std::vector& vertexShaders, std::vector& fragmentShaders, + std::vector& computeShaders, + GLShader* mainShader, uint32_t permutation ) { + std::vector::iterator it = std::find_if( shaderPipelineDescriptors.begin(), shaderPipelineDescriptors.end(), + [&]( const ShaderPipelineDescriptor& pipeline ) { + for ( const ShaderEntry& shader : vertexShaders ) { + if ( std::find( pipeline.shaderNames, pipeline.shaderNames + pipeline.shaderCount, shader ) + == pipeline.shaderNames + pipeline.shaderCount ) { + return false; + } + } + + for ( const ShaderEntry& shader : fragmentShaders ) { + if ( std::find( pipeline.shaderNames, pipeline.shaderNames + pipeline.shaderCount, shader ) + == pipeline.shaderNames + pipeline.shaderCount ) { + return false; + } + } + + for ( const ShaderEntry& shader : computeShaders ) { + if ( std::find( pipeline.shaderNames, pipeline.shaderNames + pipeline.shaderCount, shader ) + == pipeline.shaderNames + pipeline.shaderCount ) { + return false; + } + } + + return true; + } + ); + + if ( it == shaderPipelineDescriptors.end() ) { + ShaderPipelineDescriptor descriptor; + glGenProgramPipelines( 1, &descriptor.id ); + + GL_CheckErrors(); + if ( vertexShaders.size() ) { + ShaderProgramDescriptor* program = + FindShaderProgram( vertexShaders, mainShader, &mainShader->uniformsData[permutation * 3] ); + mainShader->uniformsData[permutation * 3].program = program->id; + mainShader->uniformsData[permutation * 3].uniformLocations = program->uniformLocations; + mainShader->uniformsData[permutation * 3].uniformBlockIndexes = program->uniformBlockIndexes; + mainShader->uniformsData[permutation * 3].uniformFirewall = program->uniformFirewall; + descriptor.AttachProgram( program ); + descriptor.VSProgram = *program; + + GL_CheckErrors(); + + glUseProgramStages( descriptor.id, GL_VERTEX_SHADER_BIT, program->id ); + GL_CheckErrors(); + } + if ( fragmentShaders.size() ) { + ShaderProgramDescriptor* program = + FindShaderProgram( fragmentShaders, mainShader, &mainShader->uniformsData[permutation * 3 + 1] ); + mainShader->uniformsData[permutation * 3 + 1].program = program->id; + mainShader->uniformsData[permutation * 3 + 1].uniformLocations = program->uniformLocations; + mainShader->uniformsData[permutation * 3 + 1].uniformBlockIndexes = program->uniformBlockIndexes; + mainShader->uniformsData[permutation * 3 + 1].uniformFirewall = program->uniformFirewall; + descriptor.AttachProgram( program ); + descriptor.FSProgram = *program; + + GL_CheckErrors(); + + glUseProgramStages( descriptor.id, GL_FRAGMENT_SHADER_BIT, program->id ); + GL_CheckErrors(); + } + if ( computeShaders.size() ) { + ShaderProgramDescriptor* program = + FindShaderProgram( computeShaders, mainShader, &mainShader->uniformsData[permutation * 3 + 2] ); + mainShader->uniformsData[permutation * 3 + 2].program = program->id; + mainShader->uniformsData[permutation * 3 + 2].uniformLocations = program->uniformLocations; + mainShader->uniformsData[permutation * 3 + 2].uniformBlockIndexes = program->uniformBlockIndexes; + mainShader->uniformsData[permutation * 3 + 2].uniformFirewall = program->uniformFirewall; + descriptor.AttachProgram( program ); + descriptor.CSProgram = *program; + + GL_CheckErrors(); + + glUseProgramStages( descriptor.id, GL_COMPUTE_SHADER_BIT, program->id ); + GL_CheckErrors(); + } + + shaderPipelineDescriptors.emplace_back( descriptor ); + return &shaderPipelineDescriptors.back(); } - UpdateShaderProgramUniformLocations( shader, shaderProgram ); - GL_BindProgram( shaderProgram ); - shader->SetShaderProgramUniforms( shaderProgram ); - GL_BindProgram( nullptr ); + if ( it->VSProgram.id ) { + mainShader->uniformsData[permutation * 3].program = it->VSProgram.id; + mainShader->uniformsData[permutation * 3].uniformLocations = it->VSProgram.uniformLocations; + mainShader->uniformsData[permutation * 3].uniformBlockIndexes = it->VSProgram.uniformBlockIndexes; + mainShader->uniformsData[permutation * 3].uniformFirewall = it->VSProgram.uniformFirewall; + } + if ( it->FSProgram.id ) { + mainShader->uniformsData[permutation * 3 + 1].program = it->FSProgram.id; + mainShader->uniformsData[permutation * 3 + 1].uniformLocations = it->FSProgram.uniformLocations; + mainShader->uniformsData[permutation * 3 + 1].uniformBlockIndexes = it->FSProgram.uniformBlockIndexes; + mainShader->uniformsData[permutation * 3 + 1].uniformFirewall = it->FSProgram.uniformFirewall; + } + if ( it->CSProgram.id ) { + mainShader->uniformsData[permutation * 3 + 2].program = it->CSProgram.id; + mainShader->uniformsData[permutation * 3 + 2].uniformLocations = it->CSProgram.uniformLocations; + mainShader->uniformsData[permutation * 3 + 2].uniformBlockIndexes = it->CSProgram.uniformBlockIndexes; + mainShader->uniformsData[permutation * 3 + 2].uniformFirewall = it->CSProgram.uniformFirewall; + } + return &*it; +} + +bool GLShaderManager::BuildPermutation( GLShader* shader, int macroIndex, int deformIndex ) { + size_t i = macroIndex + ( deformIndex << shader->_compileMacros.size() ); + + std::string compileMacros; + if ( !shader->GetCompileMacrosString( i, compileMacros, GLCompileMacro::VERTEX | GLCompileMacro::FRAGMENT ) ) { + return false; + } + + if ( IsUnusedPermutation( compileMacros.c_str() ) ) { + return false; + } + + // Program already exists + if ( i < shader->shaderPipelines.size() && + shader->shaderPipelines[i] ) { + return false; + } + + Log::Debug( "Building %s shader permutation with macro: %s", + shader->GetName(), + compileMacros.empty() ? "none" : compileMacros ); + + const int start = Sys::Milliseconds(); + + if ( i >= shader->shaderPipelines.size() ) { + shader->shaderPipelines.resize( ( deformIndex + 1 ) << shader->_compileMacros.size() ); + shader->uniformsData.resize( ( ( deformIndex + 1 ) << shader->_compileMacros.size() ) * 3 ); + } + + std::vector vertexShaders; + std::vector fragmentShaders; + std::vector computeShaders; + if ( shader->_hasVertexShader ) { + const uint32_t macros = shader->GetUniqueCompileMacros( macroIndex, GLCompileMacro::VERTEX ); + vertexShaders.emplace_back( ShaderEntry{ shader->_name, macros, GL_VERTEX_SHADER } ); + vertexShaders.emplace_back( ShaderEntry{ GetDeformShaderName( deformIndex ), 0, GL_VERTEX_SHADER } ); + } + if ( shader->_hasFragmentShader ) { + const uint32_t macros = shader->GetUniqueCompileMacros( macroIndex, GLCompileMacro::FRAGMENT ); + fragmentShaders.emplace_back( ShaderEntry{ shader->_name, macros, GL_FRAGMENT_SHADER } ); + } + if ( shader->_hasComputeShader ) { + computeShaders.emplace_back( ShaderEntry{ shader->_name, 0, GL_COMPUTE_SHADER } ); + } GL_CheckErrors(); + if ( glConfig2.separateShaderObjectsAvailable ) { + ShaderPipelineDescriptor* pipeline = FindShaderPipelines( vertexShaders, fragmentShaders, computeShaders, shader, + i ); + + shader->shaderPipelines[i] = pipeline->id; + } else { + std::vector shaders; + shaders.reserve( vertexShaders.size() + fragmentShaders.size() + computeShaders.size() ); + shaders.insert( shaders.end(), vertexShaders.begin(), vertexShaders.end() ); + shaders.insert( shaders.end(), fragmentShaders.begin(), fragmentShaders.end() ); + shaders.insert( shaders.end(), computeShaders.begin(), computeShaders.end() ); + + ShaderProgramDescriptor* program = FindShaderProgram( shaders, shader, &shader->uniformsData[i * 3] ); + + shader->shaderPipelines[i] = program->id; + } + + GL_CheckErrors(); + + Log::Debug( "Built in: %i ms", Sys::Milliseconds() - start ); return true; } -void GLShaderManager::buildAll() -{ +void GLShaderManager::BuildAll() { int startTime = Sys::Milliseconds(); int count = 0; + compileTime = 0; + compileCount = 0; + linkTime = 0; + linkCount = 0; - while ( !_shaderBuildQueue.empty() ) - { - GLShader& shader = *_shaderBuildQueue.front(); + while ( !_shaderBuildQueue.empty() ) { + GLShader* shader = _shaderBuildQueue.front(); - std::string shaderName = shader.GetMainShaderName(); + std::string shaderName = shader->GetMainShaderName(); - size_t numPermutations = static_cast(1) << shader.GetNumOfCompiledMacros(); - size_t i; + size_t numPermutations = static_cast( 1 ) << shader->GetNumOfCompiledMacros(); - for( i = 0; i < numPermutations; i++ ) - { - count += +buildPermutation( &shader, i, 0 ); + for( size_t i = 0; i < numPermutations; i++ ) { + count += +BuildPermutation( shader, i, 0 ); } _shaderBuildQueue.pop(); } // doesn't include deform vertex shaders, those are built elsewhere! - Log::Notice( "built %d glsl shaders in %d msec", count, Sys::Milliseconds() - startTime ); + Log::Notice( "Built %u glsl shader programs in %i ms (compile: %u in %i ms, link: %u in %i ms, init: %u in %i ms;" + " cache: loaded %u in %i ms, saved %u in %i ms)", + count, Sys::Milliseconds() - startTime, + compileCount, compileTime, linkCount, linkTime, initCount, initTime, + cacheLoadCount, cacheLoadTime, cacheSaveCount, cacheSaveTime ); } -std::string GLShaderManager::ProcessInserts( const std::string& shaderText, const uint32_t offset ) const { +std::string GLShaderManager::ProcessInserts( const std::string& shaderText ) const { std::string out; std::istringstream shaderTextStream( shaderText ); std::string line; int insertCount = 0; - int lineCount = offset; + int lineCount = 0; while ( std::getline( shaderTextStream, line, '\n' ) ) { ++lineCount; @@ -1059,8 +1377,64 @@ std::string GLShaderManager::ProcessInserts( const std::string& shaderText, cons return out; } +ShaderDescriptor* GLShaderManager::FindShader( const std::string& name, const std::string& mainText, + const GLenum type, const std::vector& headers, + const uint32_t macro, const std::string& compileMacros, const bool main ) { + + ShaderDescriptor desc{ name, compileMacros, macro, type, main }; + const std::vector::iterator it = std::find_if( shaderDescriptors.begin(), shaderDescriptors.end(), + [&]( const ShaderDescriptor& other ) { + return desc.type == other.type && desc.macro == other.macro && desc.name == other.name; + } + ); + + if ( it != shaderDescriptors.end() ) { + return nullptr; + } + + std::string combinedShaderText = BuildShaderText( mainText, headers, compileMacros ); + combinedShaderText = ProcessInserts( combinedShaderText ); + + desc.shaderSource = combinedShaderText; + + shaderDescriptors.emplace_back( desc ); + + return &shaderDescriptors.back(); +} + +std::string GLShaderManager::BuildShaderText( const std::string& mainShaderText, const std::vector& headers, + const std::string& macros ) { + std::string combinedText; + + uint32_t count = 0; + for ( GLHeader* header : headers ) { + count += header->getText().size(); + } + + combinedText.reserve( count ); + + for ( GLHeader* header : headers ) { + combinedText += header->getText(); + } + + const char* compileMacrosP = macros.c_str(); + while ( true ) { + const char* token = COM_ParseExt2( &compileMacrosP, false ); + + if ( !token[0] ) { + break; + } + + combinedText += Str::Format( "#ifndef %s\n#define %s 1\n#endif\n", token, token ); + } + + combinedText += mainShaderText; + + return combinedText; +} + void GLShaderManager::InitShader( GLShader* shader ) { - shader->_shaderPrograms = std::vector( static_cast< size_t >( 1 ) << shader->_compileMacros.size() ); + const int start = Sys::Milliseconds(); shader->PostProcessUniforms(); @@ -1077,310 +1451,250 @@ void GLShaderManager::InitShader( GLShader* shader ) { uniformBlock->SetLocationIndex( i ); } + struct ShaderType { + bool enabled; + int type; + GLenum GLType; + + const char* postfix; + uint32_t offset; + std::vector headers; + + std::string path; + std::string mainText; + }; + + ShaderType shaderTypes[] = { + { shader->_hasVertexShader, GLCompileMacro::VERTEX, GL_VERTEX_SHADER, "_vp", + GLVersionDeclaration.getText().size(), + { &GLVersionDeclaration, &GLCompatHeader, &GLEngineConstants, &GLVertexHeader } }, + { shader->_hasFragmentShader, GLCompileMacro::FRAGMENT, GL_FRAGMENT_SHADER, "_fp", + GLVersionDeclaration.getText().size(), + { &GLVersionDeclaration, &GLCompatHeader, &GLEngineConstants, &GLFragmentHeader } }, + { shader->_hasComputeShader, GLCompileMacro::COMPUTE, GL_COMPUTE_SHADER, "_cp", + GLComputeVersionDeclaration.getText().size(), + { &GLComputeVersionDeclaration, &GLCompatHeader, &GLEngineConstants, &GLComputeHeader, &GLWorldHeader } } + }; + char filename[MAX_QPATH]; - if ( shader->_hasVertexShader ) { - Com_sprintf( filename, sizeof( filename ), "%s_vp.glsl", shader->GetMainShaderName().c_str() ); - shader->_vertexShaderText = GetShaderText( filename ); + for ( ShaderType& shaderType : shaderTypes ) { + if ( shaderType.enabled ) { + Com_sprintf( filename, sizeof( filename ), "%s%s.glsl", shader->GetMainShaderName().c_str(), shaderType.postfix ); - const uint32_t offset = - GLVersionDeclaration.getLineCount() - + GLCompatHeader.getLineCount() - + GLEngineConstants.getLineCount() - + GLVertexHeader.getLineCount(); - shader->_vertexShaderText = ProcessInserts( shader->_vertexShaderText, offset ); + shaderType.path = filename; + shaderType.mainText = GetShaderText( filename ); + } } - if ( shader->_hasFragmentShader ) { - Com_sprintf( filename, sizeof( filename ), "%s_fp.glsl", shader->GetMainShaderName().c_str() ); - shader->_fragmentShaderText = GetShaderText( filename ); - const uint32_t offset = - GLVersionDeclaration.getLineCount() - + GLCompatHeader.getLineCount() - + GLEngineConstants.getLineCount() - + GLFragmentHeader.getLineCount(); - shader->_fragmentShaderText = ProcessInserts( shader->_fragmentShaderText, offset ); - } - if ( shader->_hasComputeShader ) { - Com_sprintf( filename, sizeof( filename ), "%s_cp.glsl", shader->GetMainShaderName().c_str() ); - shader->_computeShaderText = GetShaderText( filename ); - - const uint32_t offset = - GLComputeVersionDeclaration.getLineCount() - + GLCompatHeader.getLineCount() - + GLEngineConstants.getLineCount() - + GLComputeHeader.getLineCount() - + GLWorldHeader.getLineCount(); - shader->_computeShaderText = ProcessInserts( shader->_computeShaderText, offset ); - } - - if ( glConfig2.usingMaterialSystem && shader->_useMaterialSystem ) { - shader->_vertexShaderText = ShaderPostProcess( shader, shader->_vertexShaderText ); - shader->_fragmentShaderText = ShaderPostProcess( shader, shader->_fragmentShaderText ); - } - - std::string combinedShaderText; - if ( shader->_hasVertexShader || shader->_hasFragmentShader ) { - combinedShaderText = - GLVersionDeclaration.getText() - + GLCompatHeader.getText() - + GLEngineConstants.getText() - + GLVertexHeader.getText() - + GLFragmentHeader.getText(); - } else if ( shader->_hasComputeShader ) { - combinedShaderText = - GLComputeVersionDeclaration.getText() - + GLCompatHeader.getText() - + GLEngineConstants.getText() - + GLComputeHeader.getText() - + GLWorldHeader.getText(); - } + for ( uint32_t i = 0; i < BIT( shader->GetNumOfCompiledMacros() ); i++ ) { + for ( ShaderType& shaderType : shaderTypes ) { + if ( !shaderType.enabled ) { + continue; + } - if ( shader->_hasVertexShader ) { - combinedShaderText += shader->_vertexShaderText; - } - if ( shader->_hasFragmentShader ) { - combinedShaderText += shader->_fragmentShaderText; - } - if ( shader->_hasComputeShader ) { - combinedShaderText += shader->_computeShaderText; + std::string compileMacros; + if ( !shader->GetCompileMacrosString( i, compileMacros, shaderType.type ) ) { + continue; + } + + if ( IsUnusedPermutation( compileMacros.c_str() ) ) { + continue; + } + + shader->BuildShaderCompileMacros( compileMacros ); + + const uint32_t uniqueMacros = shader->GetUniqueCompileMacros( i, shaderType.type ); + + ShaderDescriptor* desc = FindShader( shader->_name, shaderType.mainText, shaderType.GLType, shaderType.headers, + uniqueMacros, compileMacros, true ); + + if ( desc && glConfig2.usingMaterialSystem && shader->_useMaterialSystem ) { + desc->shaderSource = ShaderPostProcess( shader, desc->shaderSource, shaderType.offset ); + } + + initCount++; + } } - shader->_checkSum = Com_BlockChecksum( combinedShaderText.c_str(), combinedShaderText.length() ); + initTime += Sys::Milliseconds() - start; } -bool GLShaderManager::LoadShaderBinary( GLShader *shader, size_t programNum ) -{ -#ifdef GL_ARB_get_program_binary - GLint success; - const byte *binaryptr; - GLBinaryHeader shaderHeader; - - if ( !r_glslCache.Get() ) +bool GLShaderManager::LoadShaderBinary( const std::vector& shaders, const std::string& mainShader, + ShaderProgramDescriptor* descriptor ) { + if ( !r_glslCache.Get() ) { return false; + } - if (!GetShaderPath().empty()) + if ( !GetShaderPath().empty() ) { return false; + } - // don't even try if the necessary functions aren't available - if( !glConfig2.getProgramBinaryAvailable ) + // Don't even try if the necessary functions aren't available + if ( !glConfig2.getProgramBinaryAvailable ) { return false; + } - if (_shaderBinaryCacheInvalidated) + if ( _shaderBinaryCacheInvalidated ) { return false; + } + + const int start = Sys::Milliseconds(); std::error_code err; - std::string shaderFilename = Str::Format("glsl/%s/%s_%u.bin", shader->GetName(), shader->GetName(), (unsigned int)programNum); - FS::File shaderFile = FS::HomePath::OpenRead(shaderFilename, err); - if (err) + std::string secondaryName; + for ( const ShaderEntry& shader : shaders ) { + if ( shader.name != mainShader ) { + secondaryName += Str::Format( "%s_%u_%u", shader.name, shader.macro, shader.type ); + } else { + secondaryName += Str::Format( "%u_%u_", shader.macro, shader.type ); + } + } + + std::string shaderFilename = Str::Format( "glsl/%s/%s.bin", mainShader, secondaryName ); + FS::File shaderFile = FS::HomePath::OpenRead( shaderFilename, err ); + if ( err ) { return false; + } - std::string shaderData = shaderFile.ReadAll(err); - if (err) + GLint success; + const byte *binaryptr; + GLBinaryHeader shaderHeader; + std::string shaderData = shaderFile.ReadAll( err ); + if ( err ) { return false; + } - if (shaderData.size() < sizeof(shaderHeader)) + if ( shaderData.size() < sizeof( shaderHeader ) ) { return false; + } - binaryptr = reinterpret_cast(shaderData.data()); + binaryptr = reinterpret_cast( shaderData.data() ); - // get the shader header from the file + // Get the shader header from the file memcpy( &shaderHeader, binaryptr, sizeof( shaderHeader ) ); binaryptr += sizeof( shaderHeader ); - // check if the header struct is the correct format - // and the binary was produced by the same gl driver - if (shaderHeader.version != GL_SHADER_VERSION || shaderHeader.driverVersionHash != _driverVersionHash) - { - // These two fields should be the same for all shaders. So if there is a mismatch, - // don't bother opening any of the remaining files. - Log::Notice("Invalidating shader binary cache"); + /* Check if the header struct is the correct format + and the binary was produced by the same GL driver */ + if ( shaderHeader.version != GL_SHADER_VERSION /* || shaderHeader.driverVersionHash != _driverVersionHash */ ) { + /* These two fields should be the same for all shaders. So if there is a mismatch, + don't bother opening any of the remaining files. + I've disabled the cache invalidation on driver version change, because we now also cache shader programs that use + non-empty deformVertexes. This would mean that after updating the driver, any time you load a new map with + deformVertexes, it would cause the rebuild of *all* shaders */ + Log::Notice( "Invalidating shader binary cache" ); _shaderBinaryCacheInvalidated = true; return false; } - // make sure this shader uses the same number of macros - if ( shaderHeader.numMacros != shader->GetNumOfCompiledMacros() ) + // Make sure the checksums for the source code match + if ( shaderHeader.checkSum != descriptor->checkSum ) { return false; - - // make sure this shader uses the same macros - for ( unsigned int i = 0; i < shaderHeader.numMacros; i++ ) - { - if ( shader->_compileMacros[ i ]->GetType() != shaderHeader.macros[ i ] ) - return false; } - // make sure the checksums for the source code match - if ( shaderHeader.checkSum != shader->_checkSum ) + if ( glConfig2.separateShaderObjectsAvailable && !shaderHeader.separateProgram ) { return false; + } - if ( shaderHeader.binaryLength != shaderData.size() - sizeof( shaderHeader ) ) - { + if ( shaderHeader.binaryLength != shaderData.size() - sizeof( shaderHeader ) ) { Log::Warn( "Shader cache %s has wrong size", shaderFilename ); return false; } - // load the shader - shaderProgram_t *shaderProgram = &shader->_shaderPrograms[ programNum ]; - shaderProgram->program = glCreateProgram(); - glProgramBinary( shaderProgram->program, shaderHeader.binaryFormat, binaryptr, shaderHeader.binaryLength ); - glGetProgramiv( shaderProgram->program, GL_LINK_STATUS, &success ); + // Load the shader program + descriptor->id = glCreateProgram(); + glProgramBinary( descriptor->id, shaderHeader.binaryFormat, binaryptr, shaderHeader.binaryLength ); + glGetProgramiv( descriptor->id, GL_LINK_STATUS, &success ); - if ( !success ) + if ( !success ) { return false; + } + + for ( const ShaderEntry& shader : shaders ) { + descriptor->shaderNames[descriptor->shaderCount] = shader; + descriptor->shaderCount++; + } + + cacheLoadTime += Sys::Milliseconds() - start; + cacheLoadCount++; return true; -#else - return false; -#endif } -void GLShaderManager::SaveShaderBinary( GLShader *shader, size_t programNum ) -{ -#ifdef GL_ARB_get_program_binary - GLint binaryLength; - GLuint binarySize = 0; - byte *binary; - byte *binaryptr; - GLBinaryHeader shaderHeader{}; // Zero init. - shaderProgram_t *shaderProgram; - if ( !r_glslCache.Get() ) +void GLShaderManager::SaveShaderBinary( ShaderProgramDescriptor* descriptor ) { + if ( !r_glslCache.Get() ) { return; + } - if (!GetShaderPath().empty()) + if ( !GetShaderPath().empty() ) { return; + } - // don't even try if the necessary functions aren't available - if( !glConfig2.getProgramBinaryAvailable ) - { + // Don't even try if the necessary functions aren't available + if( !glConfig2.getProgramBinaryAvailable ) { return; } - shaderProgram = &shader->_shaderPrograms[ programNum ]; + const int start = Sys::Milliseconds(); - // find output size - binarySize += sizeof( shaderHeader ); - glGetProgramiv( shaderProgram->program, GL_PROGRAM_BINARY_LENGTH, &binaryLength ); + // Find output size + GLBinaryHeader shaderHeader{}; + GLuint binarySize = sizeof( shaderHeader ); + GLint binaryLength; + glGetProgramiv( descriptor->id, GL_PROGRAM_BINARY_LENGTH, &binaryLength ); // The binary length may be 0 if there is an error. - if ( binaryLength <= 0 ) - { + if ( binaryLength <= 0 ) { return; } binarySize += binaryLength; + byte* binary; + byte* binaryptr; binaryptr = binary = ( byte* )ri.Hunk_AllocateTempMemory( binarySize ); - // reserve space for the header + // Reserve space for the header binaryptr += sizeof( shaderHeader ); - // get the program binary and write it to the buffer - glGetProgramBinary( shaderProgram->program, binaryLength, nullptr, &shaderHeader.binaryFormat, binaryptr ); + // Get the program binary and write it to the buffer + glGetProgramBinary( descriptor->id, binaryLength, nullptr, &shaderHeader.binaryFormat, binaryptr ); - // set the header + // Set the header shaderHeader.version = GL_SHADER_VERSION; - shaderHeader.numMacros = shader->_compileMacros.size(); - - for ( unsigned int i = 0; i < shaderHeader.numMacros; i++ ) - { - shaderHeader.macros[ i ] = shader->_compileMacros[ i ]->GetType(); - } shaderHeader.binaryLength = binaryLength; - shaderHeader.checkSum = shader->_checkSum; + shaderHeader.checkSum = descriptor->checkSum; shaderHeader.driverVersionHash = _driverVersionHash; - // write the header to the buffer - memcpy(binary, &shaderHeader, sizeof( shaderHeader ) ); - - auto fileName = Str::Format("glsl/%s/%s_%u.bin", shader->GetName(), shader->GetName(), (unsigned int)programNum); - ri.FS_WriteFile(fileName.c_str(), binary, binarySize); - - ri.Hunk_FreeTempMemory( binary ); -#endif -} - -void GLShaderManager::CompileGPUShaders( GLShader *shader, shaderProgram_t *program, - const std::string &compileMacros ) -{ - // permutation macros - std::string macrosString; + shaderHeader.separateProgram = glConfig2.separateShaderObjectsAvailable; - const char* compileMacrosP = compileMacros.c_str(); - while ( true ) - { - const char *token = COM_ParseExt2( &compileMacrosP, false ); + // Write the header to the buffer + memcpy( binary, &shaderHeader, sizeof( shaderHeader ) ); - if ( !token[ 0 ] ) - { - break; + std::string secondaryName; + for ( uint32_t i = 0; i < descriptor->shaderCount; i++ ) { + const ShaderEntry& shader = descriptor->shaderNames[i]; + if ( shader.name != descriptor->mainShader || !descriptor->hasMain ) { + secondaryName += Str::Format( "%s_%u_%u", shader.name, shader.macro, shader.type ); + } else { + secondaryName += Str::Format( "%u_%u_", shader.macro, shader.type ); } - - macrosString += Str::Format( "#ifndef %s\n#define %s 1\n#endif\n", token, token ); } - Log::Debug( "building %s shader permutation with macro: %s", - shader->GetMainShaderName(), - compileMacros.empty() ? "none" : compileMacros ); + std::string name = descriptor->hasMain ? descriptor->mainShader : "unknown"; + auto fileName = Str::Format( "glsl/%s/%s.bin", name, secondaryName ); + ri.FS_WriteFile( fileName.c_str(), binary, binarySize ); - // add them - std::string vertexShaderTextWithMacros = macrosString + shader->_vertexShaderText; - std::string fragmentShaderTextWithMacros = macrosString + shader->_fragmentShaderText; - std::string computeShaderTextWithMacros = macrosString + shader->_computeShaderText; - if( shader->_hasVertexShader ) { - program->VS = CompileShader( shader->GetName(), - vertexShaderTextWithMacros, - { &GLVersionDeclaration, - &GLCompatHeader, - &GLEngineConstants, - &GLVertexHeader }, - GL_VERTEX_SHADER ); - } - if ( shader->_hasFragmentShader ) { - program->FS = CompileShader( shader->GetName(), - fragmentShaderTextWithMacros, - { &GLVersionDeclaration, - &GLCompatHeader, - &GLEngineConstants, - &GLFragmentHeader }, - GL_FRAGMENT_SHADER ); - } - if ( shader->_hasComputeShader ) { - program->CS = CompileShader( shader->GetName(), - computeShaderTextWithMacros, - { &GLComputeVersionDeclaration, - &GLCompatHeader, - &GLComputeHeader, - &GLEngineConstants, - &GLWorldHeader }, - GL_COMPUTE_SHADER ); - } -} - -void GLShaderManager::CompileAndLinkGPUShaderProgram( GLShader *shader, shaderProgram_t *program, - Str::StringRef compileMacros, int deformIndex ) -{ - GLShaderManager::CompileGPUShaders( shader, program, compileMacros ); - - program->program = glCreateProgram(); - if ( shader->_hasVertexShader ) { - glAttachShader( program->program, program->VS ); - glAttachShader( program->program, _deformShaders[ deformIndex ] ); - } - if ( shader->_hasFragmentShader ) { - glAttachShader( program->program, program->FS ); - } - if ( shader->_hasComputeShader ) { - glAttachShader( program->program, program->CS ); - } + ri.Hunk_FreeTempMemory( binary ); - BindAttribLocations( program->program ); - LinkProgram( program->program ); + cacheSaveTime += Sys::Milliseconds() - start; + cacheSaveCount++; } // This will generate all the extra code for material system shaders -std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::string& shaderText ) { +std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::string& shaderText, const uint32_t offset ) { if ( !shader->std430Size ) { return shaderText; } @@ -1530,64 +1844,9 @@ std::string GLShaderManager::ShaderPostProcess( GLShader *shader, const std::str materialDefines += "\n"; - newShaderText = "#define USE_MATERIAL_SYSTEM\n" + materialStruct + materialBlock + texDataBlock + materialDefines + shaderMain; - return newShaderText; -} - -GLuint GLShaderManager::CompileShader( Str::StringRef programName, - Str::StringRef shaderText, - std::initializer_list headers, - GLenum shaderType ) const -{ - GLuint shader = glCreateShader( shaderType ); - std::vector texts(headers.size() + 1); - std::vector lengths(headers.size() + 1); - int i; - - i = 0; - for(const GLHeader *hdr : headers) { - texts[i++] = hdr->getText().data(); - } - texts[i++] = shaderText.data(); - - i = 0; - for(const GLHeader *hdr : headers) { - lengths[i++] = (GLint)hdr->getText().size(); - } - lengths[i++] = (GLint)shaderText.size(); - - GL_CheckErrors(); - - glShaderSource( shader, i, texts.data(), lengths.data() ); - - // compile shader - glCompileShader( shader ); - - GL_CheckErrors(); - - // check if shader compiled - GLint compiled; - glGetShaderiv( shader, GL_COMPILE_STATUS, &compiled ); - - if ( !compiled ) - { - std::string log = GetInfoLog( shader ); - std::vector infoLog = ParseInfoLog( log ); - PrintShaderSource( programName, shader, infoLog ); - Log::Warn( "Compile log:\n%s", log ); - switch ( shaderType ) { - case GL_VERTEX_SHADER: - ThrowShaderError( Str::Format( "Couldn't compile vertex shader: %s", programName ) ); - case GL_FRAGMENT_SHADER: - ThrowShaderError( Str::Format( "Couldn't compile fragment shader: %s", programName ) ); - case GL_COMPUTE_SHADER: - ThrowShaderError( Str::Format( "Couldn't compile compute shader: %s", programName ) ); - default: - break; - } - } - - return shader; + newShaderText = "#define USE_MATERIAL_SYSTEM\n" + materialStruct + materialBlock + texDataBlock + materialDefines; // + shaderMain; + shaderMain.insert( offset, newShaderText ); + return shaderMain; } void GLShaderManager::PrintShaderSource( Str::StringRef programName, GLuint object, std::vector& infoLog ) const @@ -1852,33 +2111,8 @@ std::string GLShaderManager::GetInfoLog( GLuint object ) const return out; } -void GLShaderManager::LinkProgram( GLuint program ) const -{ - GLint linked; - -#ifdef GL_ARB_get_program_binary - // Apparently, this is necessary to get the binary program via glGetProgramBinary - if( glConfig2.getProgramBinaryAvailable ) - { - glProgramParameteri( program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE ); - } -#endif - glLinkProgram( program ); - - glGetProgramiv( program, GL_LINK_STATUS, &linked ); - - if ( !linked ) - { - Log::Warn( "Link log:" ); - Log::Warn( GetInfoLog( program ) ); - ThrowShaderError( "Shaders failed to link!" ); - } -} - -void GLShaderManager::BindAttribLocations( GLuint program ) const -{ - for ( uint32_t i = 0; i < ATTR_INDEX_MAX; i++ ) - { +void GLShaderManager::BindAttribLocations( GLuint program ) const { + for ( uint32_t i = 0; i < ATTR_INDEX_MAX; i++ ) { glBindAttribLocation( program, i, attributeNames[ i ] ); } } @@ -2037,8 +2271,8 @@ void GLShader::RegisterUniform( GLUniform* uniform ) { } GLint GLShader::GetUniformLocation( const GLchar *uniformName ) const { - shaderProgram_t* p = GetProgram(); - return glGetUniformLocation( p->program, uniformName ); + GLuint p = GetProgram(); + return glGetUniformLocation( p, uniformName ); } // Compute std430 size/alignment and sort uniforms from highest to lowest alignment @@ -2100,22 +2334,45 @@ void GLShader::PostProcessUniforms() { } } -bool GLShader::GetCompileMacrosString( size_t permutation, std::string &compileMacrosOut ) const -{ +uint32_t GLShader::GetUniqueCompileMacros( size_t permutation, const int type ) const { + uint32_t macroOut = 0; + for ( const GLCompileMacro* macro : _compileMacros ) { + if ( permutation & macro->GetBit() ) { + if ( macro->HasConflictingMacros( permutation, _compileMacros ) ) { + continue; + } + + if ( macro->MissesRequiredMacros( permutation, _compileMacros ) ) { + continue; + } + + if ( !( macro->GetShaderTypes() & type ) ) { + continue; + } + + macroOut |= BIT( macro->GetType() ); + } + } + + return macroOut; +} + +bool GLShader::GetCompileMacrosString( size_t permutation, std::string &compileMacrosOut, const int type ) const { compileMacrosOut.clear(); - for (const GLCompileMacro* macro : _compileMacros) - { - if ( permutation & macro->GetBit() ) - { - if ( macro->HasConflictingMacros( permutation, _compileMacros ) ) - { - //Log::Notice("conflicting macro! canceling '%s'", macro->GetName()); + for ( const GLCompileMacro* macro : _compileMacros ) { + if ( permutation & macro->GetBit() ) { + if ( macro->HasConflictingMacros( permutation, _compileMacros ) ) { + return false; + } + + if ( macro->MissesRequiredMacros( permutation, _compileMacros ) ) { return false; } - if ( macro->MissesRequiredMacros( permutation, _compileMacros ) ) + if ( !( macro->GetShaderTypes() & type ) ) { return false; + } compileMacrosOut += macro->GetName(); compileMacrosOut += " "; @@ -2148,19 +2405,19 @@ GLuint GLShader::GetProgram( int deformIndex ) { // program may not be loaded yet because the shader manager hasn't yet gotten to it // so try to load it now - if ( index >= _shaderPrograms.size() || !_shaderPrograms[index].program ) { - _shaderManager->buildPermutation( this, macroIndex, deformIndex ); + if ( index >= shaderPipelines.size() || !shaderPipelines[index] ) { + _shaderManager->BuildPermutation( this, macroIndex, deformIndex ); } // program is still not loaded - if ( index >= _shaderPrograms.size() || !_shaderPrograms[index].program ) { + if ( index >= shaderPipelines.size() || !shaderPipelines[index] ) { std::string activeMacros; - size_t numMacros = _compileMacros.size(); + size_t numMacros = _compileMacros.size(); for ( size_t j = 0; j < numMacros; j++ ) { GLCompileMacro* macro = _compileMacros[j]; - int bit = macro->GetBit(); + int bit = macro->GetBit(); if ( IsMacroSet( bit ) ) { activeMacros += macro->GetName(); @@ -2171,23 +2428,22 @@ GLuint GLShader::GetProgram( int deformIndex ) { ThrowShaderError( Str::Format( "Invalid shader configuration: shader = '%s', macros = '%s'", _name, activeMacros ) ); } - return _shaderPrograms[index].program; + return shaderPipelines[index]; } -void GLShader::BindProgram( int deformIndex ) -{ +void GLShader::BindProgram( int deformIndex ) { int macroIndex = SelectProgram(); size_t index = macroIndex + ( size_t(deformIndex) << _compileMacros.size() ); // program may not be loaded yet because the shader manager hasn't yet gotten to it // so try to load it now - if ( index >= _shaderPrograms.size() || !_shaderPrograms[ index ].program ) + if ( index >= shaderPipelines.size() || !shaderPipelines[index] ) { - _shaderManager->buildPermutation( this, macroIndex, deformIndex ); + _shaderManager->BuildPermutation( this, macroIndex, deformIndex ); } // program is still not loaded - if ( index >= _shaderPrograms.size() || !_shaderPrograms[ index ].program ) + if ( index >= shaderPipelines.size() || !shaderPipelines[index] ) { std::string activeMacros; @@ -2203,29 +2459,29 @@ void GLShader::BindProgram( int deformIndex ) ThrowShaderError(Str::Format("Invalid shader configuration: shader = '%s', macros = '%s'", _name, activeMacros )); } - _currentProgram = &_shaderPrograms[ index ]; + currentPipeline = shaderPipelines[index]; + currentIndex = index; - if ( r_logFile->integer ) - { + if ( r_logFile->integer ) { std::string macros; - this->GetCompileMacrosString( index, macros ); + GetCompileMacrosString( index, macros, GLCompileMacro::VERTEX | GLCompileMacro::FRAGMENT ); - auto msg = Str::Format("--- GL_BindProgram( name = '%s', macros = '%s' ) ---\n", this->GetName(), macros); - GLimp_LogComment(msg.c_str()); + auto msg = Str::Format( "--- GL_BindProgram( name = '%s', macros = '%s' ) ---\n", this->GetName(), macros ); + GLimp_LogComment( msg.c_str() ); } - GL_BindProgram( _currentProgram ); + GL_BindProgram( currentPipeline ); } void GLShader::DispatchCompute( const GLuint globalWorkgroupX, const GLuint globalWorkgroupY, const GLuint globalWorkgroupZ ) { - ASSERT_EQ( _currentProgram, glState.currentProgram ); + ASSERT_EQ( currentPipeline, glState.currentPipeline ); ASSERT( _hasComputeShader ); glDispatchCompute( globalWorkgroupX, globalWorkgroupY, globalWorkgroupZ ); } void GLShader::DispatchComputeIndirect( const GLintptr indirectBuffer ) { - ASSERT_EQ( _currentProgram, glState.currentProgram ); + ASSERT_EQ( currentPipeline, glState.currentPipeline ); ASSERT( _hasComputeShader ); glDispatchComputeIndirect( indirectBuffer ); } @@ -2255,6 +2511,14 @@ void GLShader::WriteUniformsToBuffer( uint32_t* buffer ) { } } +void TextureUniform( GLuint program, GLint location, GLint value ) { + if ( glConfig2.separateShaderObjectsAvailable ) { + glProgramUniform1i( program, location, value ); + } else { + glUniform1i( location, value ); + } +} + GLShader_generic::GLShader_generic( GLShaderManager *manager ) : GLShader( "generic", ATTR_POSITION | ATTR_TEXCOORD | ATTR_QTANGENT | ATTR_COLOR, manager ), u_ColorMap( this ), @@ -2281,10 +2545,10 @@ GLShader_generic::GLShader_generic( GLShaderManager *manager ) : { } -void GLShader_generic::SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) +void GLShader_generic::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ColorMap" ), 0 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_DepthMap" ), 1 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_ColorMap" ), 0 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_DepthMap" ), 1 ); } GLShader_genericMaterial::GLShader_genericMaterial( GLShaderManager* manager ) : @@ -2310,9 +2574,9 @@ GLShader_genericMaterial::GLShader_genericMaterial( GLShaderManager* manager ) : GLCompileMacro_USE_DEPTH_FADE( this ) { } -void GLShader_genericMaterial::SetShaderProgramUniforms( shaderProgram_t* shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ColorMap" ), 0 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_DepthMap" ), 1 ); +void GLShader_genericMaterial::SetShaderProgramUniforms( ShaderProgramDescriptor* shaderProgram ) { + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_ColorMap" ), 0 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_DepthMap" ), 1 ); } GLShader_lightMapping::GLShader_lightMapping( GLShaderManager *manager ) : @@ -2364,22 +2628,22 @@ GLShader_lightMapping::GLShader_lightMapping( GLShaderManager *manager ) : { } -void GLShader_lightMapping::SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) +void GLShader_lightMapping::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_DiffuseMap" ), BIND_DIFFUSEMAP ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_NormalMap" ), BIND_NORMALMAP ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_HeightMap" ), BIND_HEIGHTMAP ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_MaterialMap" ), BIND_MATERIALMAP ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_LightMap" ), BIND_LIGHTMAP ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_LightGrid1" ), BIND_LIGHTMAP ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_DeluxeMap" ), BIND_DELUXEMAP ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_LightGrid2" ), BIND_DELUXEMAP ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_GlowMap" ), BIND_GLOWMAP ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_EnvironmentMap0" ), BIND_ENVIRONMENTMAP0 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_EnvironmentMap1" ), BIND_ENVIRONMENTMAP1 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_LightTiles" ), BIND_LIGHTTILES ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_DiffuseMap" ), BIND_DIFFUSEMAP ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_NormalMap" ), BIND_NORMALMAP ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_HeightMap" ), BIND_HEIGHTMAP ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_MaterialMap" ), BIND_MATERIALMAP ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_LightMap" ), BIND_LIGHTMAP ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_LightGrid1" ), BIND_LIGHTMAP ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_DeluxeMap" ), BIND_DELUXEMAP ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_LightGrid2" ), BIND_DELUXEMAP ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_GlowMap" ), BIND_GLOWMAP ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_EnvironmentMap0" ), BIND_ENVIRONMENTMAP0 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_EnvironmentMap1" ), BIND_ENVIRONMENTMAP1 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_LightTiles" ), BIND_LIGHTTILES ); if( !glConfig2.uniformBufferObjectAvailable ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_Lights" ), BIND_LIGHTS ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_Lights" ), BIND_LIGHTS ); } } @@ -2429,19 +2693,19 @@ GLShader_lightMappingMaterial::GLShader_lightMappingMaterial( GLShaderManager* m GLCompileMacro_USE_PHYSICAL_MAPPING( this ) { } -void GLShader_lightMappingMaterial::SetShaderProgramUniforms( shaderProgram_t* shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_DiffuseMap" ), BIND_DIFFUSEMAP ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_NormalMap" ), BIND_NORMALMAP ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_HeightMap" ), BIND_HEIGHTMAP ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_MaterialMap" ), BIND_MATERIALMAP ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_LightMap" ), BIND_LIGHTMAP ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_DeluxeMap" ), BIND_DELUXEMAP ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_GlowMap" ), BIND_GLOWMAP ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_EnvironmentMap0" ), BIND_ENVIRONMENTMAP0 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_EnvironmentMap1" ), BIND_ENVIRONMENTMAP1 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_LightTiles" ), BIND_LIGHTTILES ); +void GLShader_lightMappingMaterial::SetShaderProgramUniforms( ShaderProgramDescriptor* shaderProgram ) { + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_DiffuseMap" ), BIND_DIFFUSEMAP ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_NormalMap" ), BIND_NORMALMAP ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_HeightMap" ), BIND_HEIGHTMAP ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_MaterialMap" ), BIND_MATERIALMAP ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_LightMap" ), BIND_LIGHTMAP ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_DeluxeMap" ), BIND_DELUXEMAP ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_GlowMap" ), BIND_GLOWMAP ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_EnvironmentMap0" ), BIND_ENVIRONMENTMAP0 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_EnvironmentMap1" ), BIND_ENVIRONMENTMAP1 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_LightTiles" ), BIND_LIGHTTILES ); if ( !glConfig2.uniformBufferObjectAvailable ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_Lights" ), BIND_LIGHTS ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_Lights" ), BIND_LIGHTS ); } } @@ -2485,17 +2749,17 @@ GLShader_forwardLighting_omniXYZ::GLShader_forwardLighting_omniXYZ( GLShaderMana { } -void GLShader_forwardLighting_omniXYZ::SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) +void GLShader_forwardLighting_omniXYZ::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_DiffuseMap" ), 0 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_NormalMap" ), 1 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_MaterialMap" ), 2 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_AttenuationMapXY" ), 3 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_AttenuationMapZ" ), 4 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ShadowMap" ), 5 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_RandomMap" ), 6 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ShadowClipMap" ), 7 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_HeightMap" ), 15 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_DiffuseMap" ), 0 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_NormalMap" ), 1 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_MaterialMap" ), 2 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_AttenuationMapXY" ), 3 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_AttenuationMapZ" ), 4 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowMap" ), 5 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_RandomMap" ), 6 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowClipMap" ), 7 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_HeightMap" ), 15 ); } GLShader_forwardLighting_projXYZ::GLShader_forwardLighting_projXYZ( GLShaderManager *manager ): @@ -2544,17 +2808,17 @@ void GLShader_forwardLighting_projXYZ::BuildShaderCompileMacros( std::string& co compileMacros += "LIGHT_PROJ "; } -void GLShader_forwardLighting_projXYZ::SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) +void GLShader_forwardLighting_projXYZ::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_DiffuseMap" ), 0 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_NormalMap" ), 1 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_MaterialMap" ), 2 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_AttenuationMapXY" ), 3 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_AttenuationMapZ" ), 4 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ShadowMap0" ), 5 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_RandomMap" ), 6 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ShadowClipMap0" ), 7 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_HeightMap" ), 15 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_DiffuseMap" ), 0 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_NormalMap" ), 1 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_MaterialMap" ), 2 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_AttenuationMapXY" ), 3 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_AttenuationMapZ" ), 4 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowMap0" ), 5 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_RandomMap" ), 6 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowClipMap0" ), 7 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_HeightMap" ), 15 ); } GLShader_forwardLighting_directionalSun::GLShader_forwardLighting_directionalSun( GLShaderManager *manager ): @@ -2610,24 +2874,24 @@ void GLShader_forwardLighting_directionalSun::BuildShaderCompileMacros( std::str compileMacros += "LIGHT_DIRECTIONAL "; } -void GLShader_forwardLighting_directionalSun::SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) +void GLShader_forwardLighting_directionalSun::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_DiffuseMap" ), 0 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_NormalMap" ), 1 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_MaterialMap" ), 2 ); - //glUniform1i(glGetUniformLocation( shaderProgram->program, "u_AttenuationMapXY" ), 3); - //glUniform1i(glGetUniformLocation( shaderProgram->program, "u_AttenuationMapZ" ), 4); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ShadowMap0" ), 5 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ShadowMap1" ), 6 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ShadowMap2" ), 7 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ShadowMap3" ), 8 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ShadowMap4" ), 9 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ShadowClipMap0" ), 10 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ShadowClipMap1" ), 11 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ShadowClipMap2" ), 12 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ShadowClipMap3" ), 13 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ShadowClipMap4" ), 14 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_HeightMap" ), 15 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_DiffuseMap" ), 0 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_NormalMap" ), 1 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_MaterialMap" ), 2 ); + //glUniform1i(glGetUniformLocation( shaderProgram->id, "u_AttenuationMapXY" ), 3); + //glUniform1i(glGetUniformLocation( shaderProgram->id, "u_AttenuationMapZ" ), 4); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowMap0" ), 5 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowMap1" ), 6 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowMap2" ), 7 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowMap3" ), 8 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowMap4" ), 9 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowClipMap0" ), 10 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowClipMap1" ), 11 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowClipMap2" ), 12 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowClipMap3" ), 13 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ShadowClipMap4" ), 14 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_HeightMap" ), 15 ); } GLShader_shadowFill::GLShader_shadowFill( GLShaderManager *manager ) : @@ -2649,9 +2913,9 @@ GLShader_shadowFill::GLShader_shadowFill( GLShaderManager *manager ) : { } -void GLShader_shadowFill::SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) +void GLShader_shadowFill::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ColorMap" ), 0 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_ColorMap" ), 0 ); } GLShader_reflection::GLShader_reflection( GLShaderManager *manager ): @@ -2677,11 +2941,11 @@ GLShader_reflection::GLShader_reflection( GLShaderManager *manager ): { } -void GLShader_reflection::SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) +void GLShader_reflection::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ColorMap" ), 0 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_NormalMap" ), 1 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_HeightMap" ), 15 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_ColorMap" ), 0 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_NormalMap" ), 1 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_HeightMap" ), 15 ); } GLShader_reflectionMaterial::GLShader_reflectionMaterial( GLShaderManager* manager ) : @@ -2702,10 +2966,10 @@ GLShader_reflectionMaterial::GLShader_reflectionMaterial( GLShaderManager* manag GLCompileMacro_USE_RELIEF_MAPPING( this ) { } -void GLShader_reflectionMaterial::SetShaderProgramUniforms( shaderProgram_t* shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ColorMap" ), 0 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_NormalMap" ), 1 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_HeightMap" ), 15 ); +void GLShader_reflectionMaterial::SetShaderProgramUniforms( ShaderProgramDescriptor* shaderProgram ) { + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_ColorMap" ), 0 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_NormalMap" ), 1 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_HeightMap" ), 15 ); } GLShader_skybox::GLShader_skybox( GLShaderManager *manager ) : @@ -2720,10 +2984,10 @@ GLShader_skybox::GLShader_skybox( GLShaderManager *manager ) : { } -void GLShader_skybox::SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) +void GLShader_skybox::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ColorMapCube" ), 0 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_CloudMap" ), 1 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_ColorMapCube" ), 0 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_CloudMap" ), 1 ); } GLShader_skyboxMaterial::GLShader_skyboxMaterial( GLShaderManager* manager ) : @@ -2737,9 +3001,9 @@ GLShader_skyboxMaterial::GLShader_skyboxMaterial( GLShaderManager* manager ) : u_ModelViewProjectionMatrix( this ) {} -void GLShader_skyboxMaterial::SetShaderProgramUniforms( shaderProgram_t* shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ColorMap" ), 0 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_CloudMap" ), 1 ); +void GLShader_skyboxMaterial::SetShaderProgramUniforms( ShaderProgramDescriptor* shaderProgram ) { + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_ColorMap" ), 0 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_CloudMap" ), 1 ); } GLShader_fogQuake3::GLShader_fogQuake3( GLShaderManager *manager ) : @@ -2759,9 +3023,9 @@ GLShader_fogQuake3::GLShader_fogQuake3( GLShaderManager *manager ) : { } -void GLShader_fogQuake3::SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) +void GLShader_fogQuake3::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_FogMap" ), 0 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_FogMap" ), 0 ); } GLShader_fogQuake3Material::GLShader_fogQuake3Material( GLShaderManager* manager ) : @@ -2776,8 +3040,8 @@ GLShader_fogQuake3Material::GLShader_fogQuake3Material( GLShaderManager* manager GLDeformStage( this ) { } -void GLShader_fogQuake3Material::SetShaderProgramUniforms( shaderProgram_t* shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_FogMap" ), 0 ); +void GLShader_fogQuake3Material::SetShaderProgramUniforms( ShaderProgramDescriptor* shaderProgram ) { + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_FogMap" ), 0 ); } GLShader_fogGlobal::GLShader_fogGlobal( GLShaderManager *manager ) : @@ -2791,10 +3055,10 @@ GLShader_fogGlobal::GLShader_fogGlobal( GLShaderManager *manager ) : { } -void GLShader_fogGlobal::SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) +void GLShader_fogGlobal::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ColorMap" ), 0 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_DepthMap" ), 1 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_ColorMap" ), 0 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_DepthMap" ), 1 ); } GLShader_heatHaze::GLShader_heatHaze( GLShaderManager *manager ) : @@ -2816,11 +3080,11 @@ GLShader_heatHaze::GLShader_heatHaze( GLShaderManager *manager ) : { } -void GLShader_heatHaze::SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) +void GLShader_heatHaze::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_NormalMap" ), 0 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_CurrentMap" ), 1 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_HeightMap" ), 15 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_NormalMap" ), 0 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_CurrentMap" ), 1 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_HeightMap" ), 15 ); } GLShader_heatHazeMaterial::GLShader_heatHazeMaterial( GLShaderManager* manager ) : @@ -2839,10 +3103,10 @@ GLShader_heatHazeMaterial::GLShader_heatHazeMaterial( GLShaderManager* manager ) { } -void GLShader_heatHazeMaterial::SetShaderProgramUniforms( shaderProgram_t* shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_NormalMap" ), 0 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_CurrentMap" ), 1 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_HeightMap" ), 15 ); +void GLShader_heatHazeMaterial::SetShaderProgramUniforms( ShaderProgramDescriptor* shaderProgram ) { + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_NormalMap" ), 0 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_CurrentMap" ), 1 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_HeightMap" ), 15 ); } GLShader_screen::GLShader_screen( GLShaderManager *manager ) : @@ -2852,9 +3116,9 @@ GLShader_screen::GLShader_screen( GLShaderManager *manager ) : { } -void GLShader_screen::SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) +void GLShader_screen::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_CurrentMap" ), 0 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_CurrentMap" ), 0 ); } GLShader_screenMaterial::GLShader_screenMaterial( GLShaderManager* manager ) : @@ -2863,8 +3127,8 @@ GLShader_screenMaterial::GLShader_screenMaterial( GLShaderManager* manager ) : u_ModelViewProjectionMatrix( this ) { } -void GLShader_screenMaterial::SetShaderProgramUniforms( shaderProgram_t* shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_CurrentMap" ), 0 ); +void GLShader_screenMaterial::SetShaderProgramUniforms( ShaderProgramDescriptor* shaderProgram ) { + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_CurrentMap" ), 0 ); } GLShader_portal::GLShader_portal( GLShaderManager *manager ) : @@ -2876,9 +3140,9 @@ GLShader_portal::GLShader_portal( GLShaderManager *manager ) : { } -void GLShader_portal::SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) +void GLShader_portal::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_CurrentMap" ), 0 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_CurrentMap" ), 0 ); } GLShader_contrast::GLShader_contrast( GLShaderManager *manager ) : @@ -2888,9 +3152,9 @@ GLShader_contrast::GLShader_contrast( GLShaderManager *manager ) : { } -void GLShader_contrast::SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) +void GLShader_contrast::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ColorMap" ), 0 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_ColorMap" ), 0 ); } GLShader_cameraEffects::GLShader_cameraEffects( GLShaderManager *manager ) : @@ -2907,10 +3171,10 @@ GLShader_cameraEffects::GLShader_cameraEffects( GLShaderManager *manager ) : { } -void GLShader_cameraEffects::SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) +void GLShader_cameraEffects::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_CurrentMap" ), 0 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ColorMap3D" ), 3 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_CurrentMap" ), 0 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_ColorMap3D" ), 3 ); } GLShader_blur::GLShader_blur( GLShaderManager *manager ) : @@ -2923,9 +3187,9 @@ GLShader_blur::GLShader_blur( GLShaderManager *manager ) : { } -void GLShader_blur::SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) +void GLShader_blur::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ColorMap" ), 0 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_ColorMap" ), 0 ); } GLShader_debugShadowMap::GLShader_debugShadowMap( GLShaderManager *manager ) : @@ -2935,9 +3199,9 @@ GLShader_debugShadowMap::GLShader_debugShadowMap( GLShaderManager *manager ) : { } -void GLShader_debugShadowMap::SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) +void GLShader_debugShadowMap::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_CurrentMap" ), 0 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_CurrentMap" ), 0 ); } GLShader_liquid::GLShader_liquid( GLShaderManager *manager ) : @@ -2973,14 +3237,14 @@ GLShader_liquid::GLShader_liquid( GLShaderManager *manager ) : { } -void GLShader_liquid::SetShaderProgramUniforms( shaderProgram_t* shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_CurrentMap" ), 0 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_PortalMap" ), 1 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_DepthMap" ), 2 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_NormalMap" ), 3 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_LightGrid1" ), 6 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_LightGrid2" ), 7 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_HeightMap" ), 15 ); +void GLShader_liquid::SetShaderProgramUniforms( ShaderProgramDescriptor* shaderProgram ) { + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_CurrentMap" ), 0 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_PortalMap" ), 1 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_DepthMap" ), 2 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_NormalMap" ), 3 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_LightGrid1" ), 6 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_LightGrid2" ), 7 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_HeightMap" ), 15 ); } GLShader_liquidMaterial::GLShader_liquidMaterial( GLShaderManager* manager ) : @@ -3016,15 +3280,15 @@ GLShader_liquidMaterial::GLShader_liquidMaterial( GLShaderManager* manager ) : GLCompileMacro_USE_RELIEF_MAPPING( this ) { } -void GLShader_liquidMaterial::SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) +void GLShader_liquidMaterial::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_CurrentMap" ), 0 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_PortalMap" ), 1 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_DepthMap" ), 2 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_NormalMap" ), 3 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_LightGrid1" ), 6 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_LightGrid2" ), 7 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_HeightMap" ), 15 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_CurrentMap" ), 0 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_PortalMap" ), 1 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_DepthMap" ), 2 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_NormalMap" ), 3 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_LightGrid1" ), 6 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_LightGrid2" ), 7 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_HeightMap" ), 15 ); } GLShader_motionblur::GLShader_motionblur( GLShaderManager *manager ) : @@ -3036,10 +3300,10 @@ GLShader_motionblur::GLShader_motionblur( GLShaderManager *manager ) : { } -void GLShader_motionblur::SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) +void GLShader_motionblur::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ColorMap" ), 0 ); - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_DepthMap" ), 1 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_ColorMap" ), 0 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_DepthMap" ), 1 ); } GLShader_ssao::GLShader_ssao( GLShaderManager *manager ) : @@ -3051,9 +3315,9 @@ GLShader_ssao::GLShader_ssao( GLShaderManager *manager ) : { } -void GLShader_ssao::SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) +void GLShader_ssao::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_DepthMap" ), 0 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_DepthMap" ), 0 ); } GLShader_depthtile1::GLShader_depthtile1( GLShaderManager *manager ) : @@ -3064,9 +3328,9 @@ GLShader_depthtile1::GLShader_depthtile1( GLShaderManager *manager ) : { } -void GLShader_depthtile1::SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) +void GLShader_depthtile1::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_DepthMap" ), 0 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_DepthMap" ), 0 ); } GLShader_depthtile2::GLShader_depthtile2( GLShaderManager *manager ) : @@ -3076,9 +3340,9 @@ GLShader_depthtile2::GLShader_depthtile2( GLShaderManager *manager ) : { } -void GLShader_depthtile2::SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) +void GLShader_depthtile2::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_DepthMap" ), 0 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_DepthMap" ), 0 ); } GLShader_lighttile::GLShader_lighttile( GLShaderManager *manager ) : @@ -3092,12 +3356,12 @@ GLShader_lighttile::GLShader_lighttile( GLShaderManager *manager ) : { } -void GLShader_lighttile::SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) +void GLShader_lighttile::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_DepthMap" ), 0 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_DepthMap" ), 0 ); if( !glConfig2.uniformBufferObjectAvailable ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_Lights" ), 1 ); + glUniform1i( glGetUniformLocation( shaderProgram->id, "u_Lights" ), 1 ); } } @@ -3108,9 +3372,9 @@ GLShader_fxaa::GLShader_fxaa( GLShaderManager *manager ) : { } -void GLShader_fxaa::SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) +void GLShader_fxaa::SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "u_ColorMap" ), 0 ); + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "u_ColorMap" ), 0 ); } GLShader_cull::GLShader_cull( GLShaderManager* manager ) : @@ -3139,8 +3403,8 @@ GLShader_depthReduction::GLShader_depthReduction( GLShaderManager* manager ) : u_InitialDepthLevel( this ) { } -void GLShader_depthReduction::SetShaderProgramUniforms( shaderProgram_t* shaderProgram ) { - glUniform1i( glGetUniformLocation( shaderProgram->program, "depthTextureInitial" ), 0 ); +void GLShader_depthReduction::SetShaderProgramUniforms( ShaderProgramDescriptor* shaderProgram ) { + TextureUniform( shaderProgram->id, glGetUniformLocation( shaderProgram->id, "depthTextureInitial" ), 0 ); } GLShader_clearSurfaces::GLShader_clearSurfaces( GLShaderManager* manager ) : diff --git a/src/engine/renderer/gl_shader.h b/src/engine/renderer/gl_shader.h index e53b8119a2..3ee7179551 100644 --- a/src/engine/renderer/gl_shader.h +++ b/src/engine/renderer/gl_shader.h @@ -31,7 +31,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // *INDENT-OFF* static const unsigned int MAX_SHADER_MACROS = 10; -static const unsigned int GL_SHADER_VERSION = 5; +static const unsigned int GL_SHADER_VERSION = 6; class ShaderException : public std::runtime_error { @@ -47,14 +47,15 @@ enum class ShaderKind }; // Header for saved shader binaries -struct GLBinaryHeader -{ - unsigned int version; - unsigned int checkSum; // checksum of shader source this was built from - unsigned int driverVersionHash; // detect if the graphics driver was different +struct GLBinaryHeader { + uint32_t version; + uint32_t checkSum; // checksum of shader source this was built from + uint32_t driverVersionHash; // detect if the graphics driver was different + + uint32_t separateProgram; - unsigned int macros[ MAX_SHADER_MACROS ]; // macros the shader uses ( may or may not be enabled ) - unsigned int numMacros; + GLuint type; + uint32_t macro; // Bitmask of macros the shader uses ( may or may not be enabled ) GLenum binaryFormat; // argument to glProgramBinary uint32_t binaryLength; // argument to glProgramBinary @@ -68,14 +69,12 @@ class GLShaderManager; // represents a piece of GLSL code that can be copied verbatim into // GLShaders, like a .h file in C++ -class GLHeader -{ +class GLHeader { private: - - std::string _name; - std::string _text; + std::string _name; + std::string _text; uint32_t _lineCount; - GLShaderManager *_shaderManager; + GLShaderManager *_shaderManager; public: GLHeader() : _name(), _text(), _lineCount(), _shaderManager( nullptr ) @@ -85,8 +84,7 @@ class GLHeader _name( name ), _text( text ), _lineCount( std::count( text.begin(), text.end(), '\n' ) ), - _shaderManager( manager ) - { + _shaderManager( manager ) { } const std::string &getName() const { return _name; } @@ -95,44 +93,49 @@ class GLHeader const GLShaderManager *getManager() const { return _shaderManager; } }; -class GLShader -{ +class GLShader { friend class GLShaderManager; + public: + struct UniformData { + GLuint program = 0; + GLint* uniformLocations; + GLuint* uniformBlockIndexes; + byte* uniformFirewall; + }; private: GLShader( const GLShader & ) = delete; - GLShader &operator = ( const GLShader & ) = delete; + GLShader &operator = ( const GLShader & ) = delete; - std::string _name; - std::string _mainShaderName; + std::string _name; + std::string _mainShaderName; const bool _useMaterialSystem; GLuint std430Size = 0; uint padding = 0; uint textureCount = 0; protected: - int _activeMacros; - unsigned int _checkSum; - shaderProgram_t *_currentProgram; - const uint32_t _vertexAttribsRequired; - uint32_t _vertexAttribs; // can be set by uniforms - GLShaderManager *_shaderManager; - - bool _hasVertexShader; - std::string _vertexShaderText; - bool _hasFragmentShader; - std::string _fragmentShaderText; - bool _hasComputeShader; - std::string _computeShaderText; - std::vector< shaderProgram_t > _shaderPrograms; - - - size_t _uniformStorageSize; - std::vector< GLUniform * > _uniforms; - std::vector< GLUniformBlock * > _uniformBlocks; - std::vector< GLCompileMacro * > _compileMacros; - - - - + int _activeMacros; + unsigned int _checkSum; + GLuint currentPipeline; + uint32_t currentIndex; + const uint32_t _vertexAttribsRequired; + uint32_t _vertexAttribs; // can be set by uniforms + GLShaderManager *_shaderManager; + + bool _hasVertexShader; + bool _hasFragmentShader; + bool _hasComputeShader; + // std::vector shaderPrograms; + std::vector shaderPipelines; + std::vector uniformsData; + + std::vector vertexShaderDescriptors; + std::vector fragmentShaderDescriptors; + std::vector computeShaderDescriptors; + + size_t _uniformStorageSize; + std::vector _uniforms; + std::vector _uniformBlocks; + std::vector _compileMacros; GLShader( const std::string &name, uint32_t vertexAttribsRequired, GLShaderManager *manager, const bool hasVertexShader = true, const bool hasFragmentShader = true, const bool hasComputeShader = false ) : @@ -141,15 +144,13 @@ class GLShader _useMaterialSystem( false ), _activeMacros( 0 ), _checkSum( 0 ), - _currentProgram( nullptr ), _vertexAttribsRequired( vertexAttribsRequired ), _vertexAttribs( 0 ), _shaderManager( manager ), _hasVertexShader( hasVertexShader ), _hasFragmentShader( hasFragmentShader ), _hasComputeShader( hasComputeShader ), - _uniformStorageSize( 0 ) - { + _uniformStorageSize( 0 ) { } GLShader( const std::string &name, const std::string &mainShaderName, uint32_t vertexAttribsRequired, GLShaderManager *manager, @@ -159,15 +160,13 @@ class GLShader _useMaterialSystem( false ), _activeMacros( 0 ), _checkSum( 0 ), - _currentProgram( nullptr ), _vertexAttribsRequired( vertexAttribsRequired ), _vertexAttribs( 0 ), _shaderManager( manager ), _hasVertexShader( hasVertexShader ), _hasFragmentShader( hasFragmentShader ), _hasComputeShader( hasComputeShader ), - _uniformStorageSize( 0 ) - { + _uniformStorageSize( 0 ) { } GLShader( const std::string& name, const std::string& mainShaderName, const bool useMaterialSystem, uint32_t vertexAttribsRequired, @@ -178,7 +177,6 @@ class GLShader _useMaterialSystem( useMaterialSystem ), _activeMacros( 0 ), _checkSum( 0 ), - _currentProgram( nullptr ), _vertexAttribsRequired( vertexAttribsRequired ), _vertexAttribs( 0 ), _shaderManager( manager ), @@ -189,57 +187,16 @@ class GLShader } public: - virtual ~GLShader() - { - for ( std::size_t i = 0; i < _shaderPrograms.size(); i++ ) - { - shaderProgram_t *p = &_shaderPrograms[ i ]; - - if ( p->program ) - { - glDeleteProgram( p->program ); - } - - if ( p->VS ) - { - glDeleteShader( p->VS ); - } - - if ( p->FS ) - { - glDeleteShader( p->FS ); - } - - if ( p->CS ) { - glDeleteShader( p->CS ); - } - - if ( p->uniformFirewall ) - { - Z_Free( p->uniformFirewall ); - } - - if ( p->uniformLocations ) - { - Z_Free( p->uniformLocations ); - } - - if ( p->uniformBlockIndexes ) - { - Z_Free( p->uniformBlockIndexes ); - } - } + virtual ~GLShader() { } void RegisterUniform( GLUniform* uniform ); - void RegisterUniformBlock( GLUniformBlock *uniformBlock ) - { + void RegisterUniformBlock( GLUniformBlock *uniformBlock ) { _uniformBlocks.push_back( uniformBlock ); } - void RegisterCompileMacro( GLCompileMacro *compileMacro ) - { + void RegisterCompileMacro( GLCompileMacro *compileMacro ) { if ( _compileMacros.size() >= MAX_SHADER_MACROS ) { Sys::Drop( "Can't register more than %u compile macros for a single shader", MAX_SHADER_MACROS ); @@ -248,34 +205,35 @@ class GLShader _compileMacros.push_back( compileMacro ); } - size_t GetNumOfCompiledMacros() const - { + size_t GetNumOfCompiledMacros() const { return _compileMacros.size(); } + UniformData* GetUniformData( int offset = 0 ) { + return &uniformsData[currentIndex * 3 + offset]; + } + GLint GetUniformLocation( const GLchar *uniformName ) const; - shaderProgram_t *GetProgram() const - { - return _currentProgram; + GLuint GetProgram() const { + return currentPipeline; } - const std::string &GetName() const - { + const std::string &GetName() const { return _name; } - const std::string &GetMainShaderName() const - { + const std::string &GetMainShaderName() const { return _mainShaderName; } protected: - void PostProcessUniforms(); - bool GetCompileMacrosString( size_t permutation, std::string &compileMacrosOut ) const; + void PostProcessUniforms(); + uint32_t GetUniqueCompileMacros( size_t permutation, const int type ) const; + bool GetCompileMacrosString( size_t permutation, std::string &compileMacrosOut, const int type ) const; virtual void BuildShaderCompileMacros( std::string& /*vertexInlines*/ ) { }; - virtual void SetShaderProgramUniforms( shaderProgram_t* /*shaderProgram*/ ) { }; - int SelectProgram(); + virtual void SetShaderProgramUniforms( ShaderProgramDescriptor* /*shaderProgram*/ ) { }; + int SelectProgram(); public: GLuint GetProgram( int deformIndex ); void BindProgram( int deformIndex ); @@ -283,33 +241,27 @@ class GLShader void DispatchComputeIndirect( const GLintptr indirectBuffer ); void SetRequiredVertexPointers(); - bool IsMacroSet( int bit ) - { + bool IsMacroSet( int bit ) { return ( _activeMacros & bit ) != 0; } - void AddMacroBit( int bit ) - { + void AddMacroBit( int bit ) { _activeMacros |= bit; } - void DelMacroBit( int bit ) - { + void DelMacroBit( int bit ) { _activeMacros &= ~bit; } - bool IsVertexAttribSet( int bit ) - { + bool IsVertexAttribSet( int bit ) { return ( _vertexAttribs & bit ) != 0; } - void AddVertexAttribBit( int bit ) - { + void AddVertexAttribBit( int bit ) { _vertexAttribs |= bit; } - void DelVertexAttribBit( int bit ) - { + void DelVertexAttribBit( int bit ) { _vertexAttribs &= ~bit; } @@ -336,12 +288,115 @@ class GLShader void WriteUniformsToBuffer( uint32_t* buffer ); }; -class GLShaderManager -{ - std::queue< GLShader* > _shaderBuildQueue; - std::vector< std::unique_ptr< GLShader > > _shaders; - std::unordered_map< std::string, int > _deformShaderLookup; - std::vector< GLint > _deformShaders; +struct ShaderEntry { + std::string name; + uint32_t macro; + GLuint type; + + bool operator==( const ShaderEntry& other ) const { + return name == other.name && macro == other.macro && type == other.type; + } + + bool operator!=( const ShaderEntry& other ) const { + return !( *this == other ); + } +}; + +struct ShaderDescriptor { + std::string name; + + std::string macros; + uint32_t macro; + + GLenum type; + bool main = false; + + GLuint id = 0; + + std::string shaderSource; +}; + +static const uint32_t MAX_SHADER_PROGRAM_SHADERS = 16; + +struct ShaderProgramDescriptor { + GLuint id = 0; + + bool hasMain = false; + GLuint type; + + uint32_t macro = 0; + + GLuint shaders[MAX_SHADER_PROGRAM_SHADERS] {}; + ShaderEntry shaderNames[MAX_SHADER_PROGRAM_SHADERS] {}; + std::string mainShader; + uint32_t shaderCount = 0; + + GLint* uniformLocations; + GLuint* uniformBlockIndexes; + byte* uniformFirewall; + + uint32_t checkSum; + + void AttachShader( ShaderDescriptor* descriptor ) { + if ( shaderCount == MAX_SHADER_PROGRAM_SHADERS ) { + Log::Warn( "Tried to attach too many shaders to program: skipping shader %s %s", descriptor->name, descriptor->macros ); + return; + } + + if ( !shaderCount ) { + type = descriptor->type; + } else if ( type != descriptor->type ) { + type = 0; + } + + if ( descriptor->main ) { + if ( hasMain && mainShader != descriptor->name ) { + Log::Warn( "More than one shader specified as main, current: %s, new: %s, using current", + mainShader, descriptor->name ); + } else { + mainShader = descriptor->name; + hasMain = true; + } + } + + shaders[shaderCount] = descriptor->id; + + shaderNames[shaderCount].name = descriptor->name; + shaderNames[shaderCount].macro = descriptor->macro; + shaderNames[shaderCount].type = descriptor->type; + + macro |= descriptor->macro; + + shaderCount++; + }; +}; + +struct ShaderPipelineDescriptor { + GLuint id = 0; + + ShaderProgramDescriptor VSProgram; + ShaderProgramDescriptor FSProgram; + ShaderProgramDescriptor CSProgram; + + uint32_t shaderCount = 0; + ShaderEntry shaderNames[MAX_SHADER_PROGRAM_SHADERS * 3] {}; + + void AttachProgram( ShaderProgramDescriptor* descriptor ) { + ASSERT_LE( shaderCount, MAX_SHADER_PROGRAM_SHADERS ); + + for ( ; shaderCount < descriptor->shaderCount; shaderCount++ ) { + shaderNames[shaderCount] = descriptor->shaderNames[shaderCount]; + } + }; +}; + +class GLShaderManager { + std::queue _shaderBuildQueue; + std::vector> _shaders; + + uint32_t deformShaderCount = 0; + std::unordered_map _deformShaderLookup; + unsigned int _driverVersionHash; // For cache invalidation if hardware changes bool _shaderBinaryCacheInvalidated; @@ -363,11 +418,12 @@ class GLShaderManager void GenerateBuiltinHeaders(); void GenerateWorldHeaders(); - template< class T > - void load( T *& shader ) - { - if( _deformShaders.size() == 0 ) { - Q_UNUSED(getDeformShaderIndex( nullptr, 0 )); + template + void LoadShader( T *& shader ) { + if( !deformShaderCount ) { + Q_UNUSED( GetDeformShaderIndex( nullptr, 0 ) ); + initTime = 0; + initCount = 0; } shader = new T( this ); @@ -375,12 +431,12 @@ class GLShaderManager _shaders.emplace_back( shader ); _shaderBuildQueue.push( shader ); } - void freeAll(); - int getDeformShaderIndex( deformStage_t *deforms, int numDeforms ); + int GetDeformShaderIndex( deformStage_t *deforms, int numDeforms ); - bool buildPermutation( GLShader *shader, int macroIndex, int deformIndex ); - void buildAll(); + bool BuildPermutation( GLShader* shader, int macroIndex, int deformIndex ); + void BuildAll(); + void FreeAll(); private: struct InfoLogEntry { int line; @@ -389,25 +445,51 @@ class GLShaderManager std::string error; }; - bool LoadShaderBinary( GLShader *shader, size_t permutation ); - void SaveShaderBinary( GLShader *shader, size_t permutation ); - GLuint CompileShader( Str::StringRef programName, Str::StringRef shaderText, - std::initializer_list headers, - GLenum shaderType ) const; - void CompileGPUShaders( GLShader *shader, shaderProgram_t *program, - const std::string &compileMacros ); - void CompileAndLinkGPUShaderProgram( GLShader *shader, shaderProgram_t *program, - Str::StringRef compileMacros, int deformIndex ); - std::string ShaderPostProcess( GLShader *shader, const std::string& shaderText ); + std::vector shaderDescriptors; + std::vector shaderProgramDescriptors; + std::vector shaderPipelineDescriptors; + + int compileTime; + uint32_t compileCount; + int linkTime; + uint32_t linkCount; + int initTime; + uint32_t initCount; + int cacheLoadTime; + uint32_t cacheLoadCount; + int cacheSaveTime; + uint32_t cacheSaveCount; + std::string BuildDeformShaderText( const std::string& steps ); - std::string ProcessInserts( const std::string& shaderText, const uint32_t offset ) const; - void LinkProgram( GLuint program ) const; + std::string GetDeformShaderName( const int index ); + + void BuildShader( ShaderDescriptor* descriptor ); + void BuildShaderProgram( ShaderProgramDescriptor* descriptor ); + ShaderProgramDescriptor* FindShaderProgram( std::vector& shaders, GLShader* mainShader, + GLShader::UniformData* uniformData ); + ShaderPipelineDescriptor* FindShaderPipelines( + std::vector& vertexShaders, std::vector& fragmentShaders, + std::vector& computeShaders, + GLShader* mainShader, uint32_t permutation ); + void BindAttribLocations( GLuint program ) const; - void PrintShaderSource( Str::StringRef programName, GLuint object, std::vector& infoLogLines ) const; - std::vector ParseInfoLog( const std::string& infoLog ) const; + void UpdateShaderProgramUniformLocations( GLShader* shader, ShaderProgramDescriptor* shaderProgram ) const; + + bool LoadShaderBinary( const std::vector& shaders, const std::string& mainShader, + ShaderProgramDescriptor* out ); + void SaveShaderBinary( ShaderProgramDescriptor* descriptor ); + std::string GetInfoLog( GLuint object ) const; - void InitShader( GLShader *shader ); - void UpdateShaderProgramUniformLocations( GLShader *shader, shaderProgram_t *shaderProgram ) const; + std::vector ParseInfoLog( const std::string& infoLog ) const; + void PrintShaderSource( Str::StringRef programName, GLuint object, std::vector& infoLogLines ) const; + + std::string ProcessInserts( const std::string& shaderText ) const; + ShaderDescriptor* FindShader( const std::string& name, const std::string& mainText, + const GLenum type, const std::vector& headers, + const uint32_t macro = 0, const std::string& compileMacros = "", const bool main = false ); + std::string BuildShaderText( const std::string& mainShaderText, const std::vector& headers, const std::string& macros ); + void InitShader( GLShader* shader ); + std::string ShaderPostProcess( GLShader *shader, const std::string& shaderText, const uint32_t offset ); }; class GLUniform @@ -486,9 +568,9 @@ class GLUniform // This should return a pointer to the memory right after the one this uniform wrote to virtual uint32_t* WriteToBuffer( uint32_t* buffer ); - void UpdateShaderProgramUniformLocation( shaderProgram_t *shaderProgram ) + void UpdateShaderProgramUniformLocation( ShaderProgramDescriptor* shaderProgram ) { - shaderProgram->uniformLocations[ _locationIndex ] = glGetUniformLocation( shaderProgram->program, GetName() ); + shaderProgram->uniformLocations[_locationIndex] = glGetUniformLocation( shaderProgram->id, GetName() ); } virtual size_t GetSize() @@ -505,13 +587,15 @@ class GLUniformSampler : protected GLUniform { } inline GLint GetLocation() { - shaderProgram_t* p = _shader->GetProgram(); + GLuint p = _shader->GetProgram(); if ( _global || !_shader->UseMaterialSystem() ) { - ASSERT_EQ( p, glState.currentProgram ); + ASSERT_EQ( p, glState.currentPipeline ); } - return p->uniformLocations[_locationIndex]; + GLShader::UniformData* FSData = _shader->GetUniformData( 1 ); + GLShader::UniformData* CSData = _shader->GetUniformData( 2 ); + return FSData->program ? FSData->uniformLocations[_locationIndex] : CSData->uniformLocations[_locationIndex]; } inline size_t GetFirewallIndex() const { @@ -531,7 +615,10 @@ class GLUniformSampler : protected GLUniform { currentValueBindless = value; if ( glConfig2.usingBindlessTextures && ( !_shader->UseMaterialSystem() || _global ) ) { - glUniformHandleui64ARB( GetLocation(), currentValueBindless ); + GLShader::UniformData* FSData = _shader->GetUniformData( 1 ); + GLShader::UniformData* CSData = _shader->GetUniformData( 2 ); + GLuint program = FSData->program ? FSData->program : CSData->program; + glProgramUniformHandleui64ARB( program, GetLocation(), currentValueBindless ); } } @@ -559,13 +646,15 @@ class GLUniformSampler1D : protected GLUniformSampler { } inline GLint GetLocation() { - shaderProgram_t* p = _shader->GetProgram(); + GLuint p = _shader->GetProgram(); if ( _global || !_shader->UseMaterialSystem() ) { - ASSERT_EQ( p, glState.currentProgram ); + ASSERT_EQ( p, glState.currentPipeline ); } - return p->uniformLocations[_locationIndex]; + GLShader::UniformData* FSData = _shader->GetUniformData( 1 ); + GLShader::UniformData* CSData = _shader->GetUniformData( 2 ); + return FSData->program ? FSData->uniformLocations[_locationIndex] : CSData->uniformLocations[_locationIndex]; } public: @@ -581,13 +670,15 @@ class GLUniformSampler2D : protected GLUniformSampler { } inline GLint GetLocation() { - shaderProgram_t* p = _shader->GetProgram(); + GLuint p = _shader->GetProgram(); if ( _global || !_shader->UseMaterialSystem() ) { - ASSERT_EQ( p, glState.currentProgram ); + ASSERT_EQ( p, glState.currentPipeline ); } - return p->uniformLocations[_locationIndex]; + GLShader::UniformData* FSData = _shader->GetUniformData( 1 ); + GLShader::UniformData* CSData = _shader->GetUniformData( 2 ); + return FSData->program ? FSData->uniformLocations[_locationIndex] : CSData->uniformLocations[_locationIndex]; } public: @@ -603,13 +694,15 @@ class GLUniformSampler3D : protected GLUniformSampler { } inline GLint GetLocation() { - shaderProgram_t* p = _shader->GetProgram(); + GLuint p = _shader->GetProgram(); if ( _global || !_shader->UseMaterialSystem() ) { - ASSERT_EQ( p, glState.currentProgram ); + ASSERT_EQ( p, glState.currentPipeline ); } - return p->uniformLocations[_locationIndex]; + GLShader::UniformData* FSData = _shader->GetUniformData( 1 ); + GLShader::UniformData* CSData = _shader->GetUniformData( 2 ); + return FSData->program ? FSData->uniformLocations[_locationIndex] : CSData->uniformLocations[_locationIndex]; } public: @@ -625,13 +718,15 @@ class GLUniformUSampler3D : protected GLUniformSampler { } inline GLint GetLocation() { - shaderProgram_t* p = _shader->GetProgram(); + GLuint p = _shader->GetProgram(); if ( _global || !_shader->UseMaterialSystem() ) { - ASSERT_EQ( p, glState.currentProgram ); + ASSERT_EQ( p, glState.currentPipeline ); } - return p->uniformLocations[_locationIndex]; + GLShader::UniformData* FSData = _shader->GetUniformData( 1 ); + GLShader::UniformData* CSData = _shader->GetUniformData( 2 ); + return FSData->program ? FSData->uniformLocations[_locationIndex] : CSData->uniformLocations[_locationIndex]; } public: @@ -647,13 +742,15 @@ class GLUniformSamplerCube : protected GLUniformSampler { } inline GLint GetLocation() { - shaderProgram_t* p = _shader->GetProgram(); + GLuint p = _shader->GetProgram(); if ( _global || !_shader->UseMaterialSystem() ) { - ASSERT_EQ( p, glState.currentProgram ); + ASSERT_EQ( p, glState.currentPipeline ); } - return p->uniformLocations[_locationIndex]; + GLShader::UniformData* FSData = _shader->GetUniformData( 1 ); + GLShader::UniformData* CSData = _shader->GetUniformData( 2 ); + return FSData->program ? FSData->uniformLocations[_locationIndex] : CSData->uniformLocations[_locationIndex]; } public: @@ -666,16 +763,14 @@ class GLUniform1i : protected GLUniform { protected: GLUniform1i( GLShader *shader, const char *name, const bool global = false ) : - GLUniform( shader, name, "int", 1, 1, global ) - { + GLUniform( shader, name, "int", 1, 1, global ) { } - inline void SetValue( int value ) - { - shaderProgram_t *p = _shader->GetProgram(); + inline void SetValue( int value ) { + GLuint program = _shader->GetProgram(); - if ( _global || !_shader->UseMaterialSystem() ) { - ASSERT_EQ( p, glState.currentProgram ); + if ( !glConfig2.separateShaderObjectsAvailable && ( _global || !_shader->UseMaterialSystem() ) ) { + ASSERT_EQ( program, glState.currentPipeline ); } #if defined( LOG_GLSL_UNIFORMS ) @@ -691,17 +786,37 @@ class GLUniform1i : protected GLUniform return; } + if ( glConfig2.separateShaderObjectsAvailable ) { + for ( int i = 0; i < 3; i++ ) { + GLShader::UniformData* p = _shader->GetUniformData( i ); + if ( !p->program ) { + continue; + } + #if defined( USE_UNIFORM_FIREWALL ) - int *firewall = ( int * ) &p->uniformFirewall[ _firewallIndex ]; + int* firewall = ( int* ) &p->uniformFirewall[_firewallIndex]; - if ( *firewall == value ) - { - return; - } + if ( *firewall == value ) { + continue; + } + + *firewall = value; +#endif + glProgramUniform1i( p->program, p->uniformLocations[_locationIndex], value ); + } + } else { + GLShader::UniformData* p = _shader->GetUniformData(); +#if defined( USE_UNIFORM_FIREWALL ) + int* firewall = ( int* ) &p->uniformFirewall[_firewallIndex]; - *firewall = value; + if ( *firewall == value ) { + return; + } + + *firewall = value; #endif - glUniform1i( p->uniformLocations[ _locationIndex ], value ); + glUniform1i( p->uniformLocations[_locationIndex], value ); + } } public: size_t GetSize() override @@ -725,10 +840,10 @@ class GLUniform1ui : protected GLUniform { } inline void SetValue( uint value ) { - shaderProgram_t* p = _shader->GetProgram(); + GLuint program = _shader->GetProgram(); - if ( _global || !_shader->UseMaterialSystem() ) { - ASSERT_EQ( p, glState.currentProgram ); + if ( !glConfig2.separateShaderObjectsAvailable && ( _global || !_shader->UseMaterialSystem() ) ) { + ASSERT_EQ( program, glState.currentPipeline ); } #if defined( LOG_GLSL_UNIFORMS ) @@ -743,16 +858,38 @@ class GLUniform1ui : protected GLUniform { return; } + + if ( glConfig2.separateShaderObjectsAvailable ) { + for ( int i = 0; i < 3; i++ ) { + GLShader::UniformData* p = _shader->GetUniformData( i ); + if ( !p->program ) { + continue; + } + #if defined( USE_UNIFORM_FIREWALL ) - uint* firewall = ( uint* ) &p->uniformFirewall[_firewallIndex]; + uint* firewall = ( uint* ) &p->uniformFirewall[_firewallIndex]; - if ( *firewall == value ) { - return; - } + if ( *firewall == value ) { + continue; + } + + *firewall = value; +#endif + glProgramUniform1ui( p->program, p->uniformLocations[_locationIndex], value ); + } + } else { + GLShader::UniformData* p = _shader->GetUniformData(); +#if defined( USE_UNIFORM_FIREWALL ) + uint* firewall = ( uint* ) &p->uniformFirewall[_firewallIndex]; + + if ( *firewall == value ) { + return; + } - *firewall = value; + *firewall = value; #endif - glUniform1ui( p->uniformLocations[_locationIndex], value ); + glUniform1ui( p->uniformLocations[_locationIndex], value ); + } } public: size_t GetSize() override { @@ -776,10 +913,10 @@ class GLUniform1Bool : protected GLUniform { } inline void SetValue( int value ) { - shaderProgram_t* p = _shader->GetProgram(); + GLuint program = _shader->GetProgram(); - if ( _global || !_shader->UseMaterialSystem() ) { - ASSERT_EQ( p, glState.currentProgram ); + if ( !glConfig2.separateShaderObjectsAvailable && ( _global || !_shader->UseMaterialSystem() ) ) { + ASSERT_EQ( program, glState.currentPipeline ); } #if defined( LOG_GLSL_UNIFORMS ) @@ -794,16 +931,38 @@ class GLUniform1Bool : protected GLUniform { return; } + + if ( glConfig2.separateShaderObjectsAvailable ) { + for ( int i = 0; i < 3; i++ ) { + GLShader::UniformData* p = _shader->GetUniformData( i ); + if ( !p->program ) { + continue; + } + #if defined( USE_UNIFORM_FIREWALL ) - int* firewall = ( int* ) &p->uniformFirewall[_firewallIndex]; + int* firewall = ( int* ) &p->uniformFirewall[_firewallIndex]; - if ( *firewall == value ) { - return; - } + if ( *firewall == value ) { + continue; + } - *firewall = value; + *firewall = value; #endif - glUniform1i( p->uniformLocations[_locationIndex], value ); + glProgramUniform1i( p->program, p->uniformLocations[_locationIndex], value ); + } + } else { + GLShader::UniformData* p = _shader->GetUniformData(); +#if defined( USE_UNIFORM_FIREWALL ) + int* firewall = ( int* ) &p->uniformFirewall[_firewallIndex]; + + if ( *firewall == value ) { + return; + } + + *firewall = value; +#endif + glUniform1i( p->uniformLocations[_locationIndex], value ); + } } public: @@ -824,16 +983,14 @@ class GLUniform1f : protected GLUniform { protected: GLUniform1f( GLShader *shader, const char *name, const bool global = false ) : - GLUniform( shader, name, "float", 1, 1, global ) - { + GLUniform( shader, name, "float", 1, 1, global ) { } - inline void SetValue( float value ) - { - shaderProgram_t *p = _shader->GetProgram(); + inline void SetValue( float value ) { + GLuint program = _shader->GetProgram(); - if ( _global || !_shader->UseMaterialSystem() ) { - ASSERT_EQ( p, glState.currentProgram ); + if ( !glConfig2.separateShaderObjectsAvailable && ( _global || !_shader->UseMaterialSystem() ) ) { + ASSERT_EQ( program, glState.currentPipeline ); } #if defined( LOG_GLSL_UNIFORMS ) @@ -849,17 +1006,37 @@ class GLUniform1f : protected GLUniform return; } + if ( glConfig2.separateShaderObjectsAvailable ) { + for ( int i = 0; i < 3; i++ ) { + GLShader::UniformData* p = _shader->GetUniformData( i ); + if ( !p->program ) { + continue; + } + #if defined( USE_UNIFORM_FIREWALL ) - float *firewall = ( float * ) &p->uniformFirewall[ _firewallIndex ]; + float* firewall = ( float* ) &p->uniformFirewall[_firewallIndex]; - if ( *firewall == value ) - { - return; - } + if ( *firewall == value ) { + continue; + } + + *firewall = value; +#endif + glProgramUniform1f( p->program, p->uniformLocations[_locationIndex], value ); + } + } else { + GLShader::UniformData* p = _shader->GetUniformData(); +#if defined( USE_UNIFORM_FIREWALL ) + float* firewall = ( float* ) &p->uniformFirewall[_firewallIndex]; + + if ( *firewall == value ) { + return; + } - *firewall = value; + *firewall = value; #endif - glUniform1f( p->uniformLocations[ _locationIndex ], value ); + glUniform1f( p->uniformLocations[_locationIndex], value ); + } } public: size_t GetSize() override @@ -880,17 +1057,15 @@ class GLUniform1fv : protected GLUniform { protected: GLUniform1fv( GLShader *shader, const char *name, const int size ) : - GLUniform( shader, name, "float", 1, 1, false, size ) - { + GLUniform( shader, name, "float", 1, 1, false, size ) { currentValue.reserve( size ); } - inline void SetValue( int numFloats, float *f ) - { - shaderProgram_t *p = _shader->GetProgram(); + inline void SetValue( int numFloats, float *f ) { + GLuint program = _shader->GetProgram(); - if ( _global || !_shader->UseMaterialSystem() ) { - ASSERT_EQ( p, glState.currentProgram ); + if ( !glConfig2.separateShaderObjectsAvailable && ( _global || !_shader->UseMaterialSystem() ) ) { + ASSERT_EQ( program, glState.currentPipeline ); } #if defined( LOG_GLSL_UNIFORMS ) @@ -906,7 +1081,19 @@ class GLUniform1fv : protected GLUniform return; } - glUniform1fv( p->uniformLocations[ _locationIndex ], numFloats, f ); + if ( glConfig2.separateShaderObjectsAvailable ) { + for ( int i = 0; i < 3; i++ ) { + GLShader::UniformData* p = _shader->GetUniformData( i ); + if ( !p->program ) { + continue; + } + + glProgramUniform1fv( p->program, p->uniformLocations[_locationIndex], numFloats, f ); + } + } else { + GLShader::UniformData* p = _shader->GetUniformData(); + glUniform1fv( p->uniformLocations[_locationIndex], numFloats, f ); + } } uint32_t* WriteToBuffer( uint32_t* buffer ) override { @@ -922,18 +1109,16 @@ class GLUniform2f : protected GLUniform { protected: GLUniform2f( GLShader *shader, const char *name ) : - GLUniform( shader, name, "vec2", 2, 2, false ) - { + GLUniform( shader, name, "vec2", 2, 2, false ) { currentValue[0] = 0.0; currentValue[1] = 0.0; } - inline void SetValue( const vec2_t v ) - { - shaderProgram_t *p = _shader->GetProgram(); + inline void SetValue( const vec2_t v ) { + GLuint program = _shader->GetProgram(); - if ( _global || !_shader->UseMaterialSystem() ) { - ASSERT_EQ( p, glState.currentProgram ); + if ( !glConfig2.separateShaderObjectsAvailable && ( _global || !_shader->UseMaterialSystem() ) ) { + ASSERT_EQ( program, glState.currentPipeline ); } #if defined( LOG_GLSL_UNIFORMS ) @@ -949,18 +1134,39 @@ class GLUniform2f : protected GLUniform return; } + + if ( glConfig2.separateShaderObjectsAvailable ) { + for ( int i = 0; i < 3; i++ ) { + GLShader::UniformData* p = _shader->GetUniformData( i ); + if ( !p->program ) { + continue; + } #if defined( USE_UNIFORM_FIREWALL ) - vec2_t *firewall = ( vec2_t * ) &p->uniformFirewall[ _firewallIndex ]; + vec2_t* firewall = ( vec2_t* ) &p->uniformFirewall[_firewallIndex]; - if ( ( *firewall )[ 0 ] == v[ 0 ] && ( *firewall )[ 1 ] == v[ 1 ] ) - { - return; - } + if ( ( *firewall )[0] == v[0] && ( *firewall )[1] == v[1] ) { + continue; + } - ( *firewall )[ 0 ] = v[ 0 ]; - ( *firewall )[ 1 ] = v[ 1 ]; + ( *firewall )[0] = v[0]; + ( *firewall )[1] = v[1]; #endif - glUniform2f( p->uniformLocations[ _locationIndex ], v[ 0 ], v[ 1 ] ); + glProgramUniform2f( p->program, p->uniformLocations[_locationIndex], v[0], v[1] ); + } + } else { + GLShader::UniformData* p = _shader->GetUniformData(); +#if defined( USE_UNIFORM_FIREWALL ) + vec2_t* firewall = ( vec2_t* ) &p->uniformFirewall[_firewallIndex]; + + if ( ( *firewall )[0] == v[0] && ( *firewall )[1] == v[1] ) { + return; + } + + ( *firewall )[0] = v[0]; + ( *firewall )[1] = v[1]; +#endif + glUniform2f( p->uniformLocations[_locationIndex], v[0], v[1] ); + } } size_t GetSize() override @@ -981,19 +1187,17 @@ class GLUniform3f : protected GLUniform { protected: GLUniform3f( GLShader *shader, const char *name, const bool global = false ) : - GLUniform( shader, name, "vec3", 3, 4, global ) - { + GLUniform( shader, name, "vec3", 3, 4, global ) { currentValue[0] = 0.0; currentValue[1] = 0.0; currentValue[2] = 0.0; } - inline void SetValue( const vec3_t v ) - { - shaderProgram_t *p = _shader->GetProgram(); + inline void SetValue( const vec3_t v ) { + GLuint program = _shader->GetProgram(); - if ( _global || !_shader->UseMaterialSystem() ) { - ASSERT_EQ( p, glState.currentProgram ); + if ( !glConfig2.separateShaderObjectsAvailable && ( _global || !_shader->UseMaterialSystem() ) ) { + ASSERT_EQ( program, glState.currentPipeline ); } #if defined( LOG_GLSL_UNIFORMS ) @@ -1009,17 +1213,37 @@ class GLUniform3f : protected GLUniform return; } + + if ( glConfig2.separateShaderObjectsAvailable ) { + for ( int i = 0; i < 3; i++ ) { + GLShader::UniformData* p = _shader->GetUniformData( i ); + if ( !p->program ) { + continue; + } #if defined( USE_UNIFORM_FIREWALL ) - vec3_t *firewall = ( vec3_t * ) &p->uniformFirewall[ _firewallIndex ]; + vec3_t* firewall = ( vec3_t* ) &p->uniformFirewall[_firewallIndex]; - if ( VectorCompare( *firewall, v ) ) - { - return; - } + if ( VectorCompare( *firewall, v ) ) { + continue; + } + + VectorCopy( v, *firewall ); +#endif + glProgramUniform3f( p->program, p->uniformLocations[_locationIndex], v[0], v[1], v[2] ); + } + } else { + GLShader::UniformData* p = _shader->GetUniformData(); +#if defined( USE_UNIFORM_FIREWALL ) + vec3_t* firewall = ( vec3_t* ) &p->uniformFirewall[_firewallIndex]; - VectorCopy( v, *firewall ); + if ( VectorCompare( *firewall, v ) ) { + return; + } + + VectorCopy( v, *firewall ); #endif - glUniform3f( p->uniformLocations[ _locationIndex ], v[ 0 ], v[ 1 ], v[ 2 ] ); + glUniform3f( p->uniformLocations[_locationIndex], v[0], v[1], v[2] ); + } } public: size_t GetSize() override @@ -1040,20 +1264,18 @@ class GLUniform4f : protected GLUniform { protected: GLUniform4f( GLShader *shader, const char *name, const bool global = false ) : - GLUniform( shader, name, "vec4", 4, 4, global ) - { + GLUniform( shader, name, "vec4", 4, 4, global ) { currentValue[0] = 0.0; currentValue[1] = 0.0; currentValue[2] = 0.0; currentValue[3] = 0.0; } - inline void SetValue( const vec4_t v ) - { - shaderProgram_t *p = _shader->GetProgram(); + inline void SetValue( const vec4_t v ) { + GLuint program = _shader->GetProgram(); - if ( _global || !_shader->UseMaterialSystem() ) { - ASSERT_EQ( p, glState.currentProgram ); + if ( !glConfig2.separateShaderObjectsAvailable && ( _global || !_shader->UseMaterialSystem() ) ) { + ASSERT_EQ( program, glState.currentPipeline ); } #if defined( LOG_GLSL_UNIFORMS ) @@ -1069,17 +1291,38 @@ class GLUniform4f : protected GLUniform return; } + + if ( glConfig2.separateShaderObjectsAvailable ) { + for ( int i = 0; i < 3; i++ ) { + GLShader::UniformData* p = _shader->GetUniformData( i ); + if ( !p->program ) { + continue; + } + #if defined( USE_UNIFORM_FIREWALL ) - vec4_t *firewall = ( vec4_t * ) &p->uniformFirewall[ _firewallIndex ]; + vec4_t* firewall = ( vec4_t* ) &p->uniformFirewall[_firewallIndex]; - if ( !memcmp( *firewall, v, sizeof( *firewall ) ) ) - { - return; - } + if ( !memcmp( *firewall, v, sizeof( *firewall ) ) ) { + continue; + } + + Vector4Copy( v, *firewall ); +#endif + glProgramUniform4f( p->program, p->uniformLocations[_locationIndex], v[0], v[1], v[2], v[3] ); + } + } else { + GLShader::UniformData* p = _shader->GetUniformData(); +#if defined( USE_UNIFORM_FIREWALL ) + vec4_t* firewall = ( vec4_t* ) &p->uniformFirewall[_firewallIndex]; + + if ( !memcmp( *firewall, v, sizeof( *firewall ) ) ) { + return; + } - Vector4Copy( v, *firewall ); + Vector4Copy( v, *firewall ); #endif - glUniform4f( p->uniformLocations[ _locationIndex ], v[ 0 ], v[ 1 ], v[ 2 ], v[ 3 ] ); + glUniform4f( p->uniformLocations[_locationIndex], v[0], v[1], v[2], v[3] ); + } } public: size_t GetSize() override @@ -1100,17 +1343,15 @@ class GLUniform4fv : protected GLUniform { protected: GLUniform4fv( GLShader *shader, const char *name, const int size ) : - GLUniform( shader, name, "vec4", 4, 4, false, size ) - { + GLUniform( shader, name, "vec4", 4, 4, false, size ) { currentValue.reserve( size ); } - inline void SetValue( int numV, vec4_t *v ) - { - shaderProgram_t *p = _shader->GetProgram(); + inline void SetValue( int numV, vec4_t *v ) { + GLuint program = _shader->GetProgram(); - if ( _global || !_shader->UseMaterialSystem() ) { - ASSERT_EQ( p, glState.currentProgram ); + if ( !glConfig2.separateShaderObjectsAvailable && ( _global || !_shader->UseMaterialSystem() ) ) { + ASSERT_EQ( program, glState.currentPipeline ); } #if defined( LOG_GLSL_UNIFORMS ) @@ -1126,7 +1367,18 @@ class GLUniform4fv : protected GLUniform return; } - glUniform4fv( p->uniformLocations[ _locationIndex ], numV, &v[ 0 ][ 0 ] ); + if ( glConfig2.separateShaderObjectsAvailable ) { + for ( int i = 0; i < 3; i++ ) { + GLShader::UniformData* p = _shader->GetUniformData( i ); + if ( !p->program ) { + continue; + } + glProgramUniform4fv( p->program, p->uniformLocations[_locationIndex], numV, &v[0][0] ); + } + } else { + GLShader::UniformData* p = _shader->GetUniformData(); + glUniform4fv( p->uniformLocations[_locationIndex], numV, &v[0][0] ); + } } public: @@ -1143,17 +1395,15 @@ class GLUniformMatrix4f : protected GLUniform { protected: GLUniformMatrix4f( GLShader *shader, const char *name, const bool global = false ) : - GLUniform( shader, name, "mat4", 16, 4, global ) - { + GLUniform( shader, name, "mat4", 16, 4, global ) { MatrixIdentity( currentValue ); } - inline void SetValue( GLboolean transpose, const matrix_t m ) - { - shaderProgram_t *p = _shader->GetProgram(); + inline void SetValue( GLboolean transpose, const matrix_t m ) { + GLuint program = _shader->GetProgram(); - if ( _global || !_shader->UseMaterialSystem() ) { - ASSERT_EQ( p, glState.currentProgram ); + if ( !glConfig2.separateShaderObjectsAvailable && ( _global || !_shader->UseMaterialSystem() ) ) { + ASSERT_EQ( program, glState.currentPipeline ); } #if defined( LOG_GLSL_UNIFORMS ) @@ -1171,17 +1421,37 @@ class GLUniformMatrix4f : protected GLUniform return; } + + if ( glConfig2.separateShaderObjectsAvailable ) { + for ( int i = 0; i < 3; i++ ) { + GLShader::UniformData* p = _shader->GetUniformData( i ); + if ( !p->program ) { + continue; + } #if defined( USE_UNIFORM_FIREWALL ) - matrix_t *firewall = ( matrix_t * ) &p->uniformFirewall[ _firewallIndex ]; + matrix_t* firewall = ( matrix_t* ) &p->uniformFirewall[_firewallIndex]; - if ( MatrixCompare( m, *firewall ) ) - { - return; - } + if ( MatrixCompare( m, *firewall ) ) { + continue; + } - MatrixCopy( m, *firewall ); + MatrixCopy( m, *firewall ); #endif - glUniformMatrix4fv( p->uniformLocations[ _locationIndex ], 1, transpose, m ); + glProgramUniformMatrix4fv( p->program, p->uniformLocations[_locationIndex], 1, transpose, m ); + } + } else { + GLShader::UniformData* p = _shader->GetUniformData(); +#if defined( USE_UNIFORM_FIREWALL ) + matrix_t* firewall = ( matrix_t* ) &p->uniformFirewall[_firewallIndex]; + + if ( MatrixCompare( m, *firewall ) ) { + return; + } + + MatrixCopy( m, *firewall ); +#endif + glUniformMatrix4fv( p->uniformLocations[_locationIndex], 1, transpose, m ); + } } public: size_t GetSize() override @@ -1205,10 +1475,10 @@ class GLUniformMatrix32f : protected GLUniform { } inline void SetValue( GLboolean transpose, const vec_t* m ) { - shaderProgram_t* p = _shader->GetProgram(); + GLuint program = _shader->GetProgram(); - if ( _global || !_shader->UseMaterialSystem() ) { - ASSERT_EQ( p, glState.currentProgram ); + if ( !glConfig2.separateShaderObjectsAvailable && ( _global || !_shader->UseMaterialSystem() ) ) { + ASSERT_EQ( program, glState.currentPipeline ); } #if defined( LOG_GLSL_UNIFORMS ) @@ -1224,7 +1494,18 @@ class GLUniformMatrix32f : protected GLUniform { return; } - glUniformMatrix3x2fv( p->uniformLocations[_locationIndex], 1, transpose, m ); + if ( glConfig2.separateShaderObjectsAvailable ) { + for ( int i = 0; i < 3; i++ ) { + GLShader::UniformData* p = _shader->GetUniformData( i ); + if ( !p->program ) { + continue; + } + glProgramUniformMatrix3x2fv( p->program, p->uniformLocations[_locationIndex], 1, transpose, m ); + } + } else { + GLShader::UniformData* p = _shader->GetUniformData(); + glUniformMatrix3x2fv( p->uniformLocations[_locationIndex], 1, transpose, m ); + } } public: size_t GetSize() override { @@ -1244,17 +1525,15 @@ class GLUniformMatrix4fv : protected GLUniform { protected: GLUniformMatrix4fv( GLShader *shader, const char *name, const int size ) : - GLUniform( shader, name, "mat4", 16, 4, false, size ) - { + GLUniform( shader, name, "mat4", 16, 4, false, size ) { currentValue.reserve( size * 16 ); } - inline void SetValue( int numMatrices, GLboolean transpose, const matrix_t *m ) - { - shaderProgram_t *p = _shader->GetProgram(); + inline void SetValue( int numMatrices, GLboolean transpose, const matrix_t *m ) { + GLuint program = _shader->GetProgram(); - if ( _global || !_shader->UseMaterialSystem() ) { - ASSERT_EQ( p, glState.currentProgram ); + if ( !glConfig2.separateShaderObjectsAvailable && ( _global || !_shader->UseMaterialSystem() ) ) { + ASSERT_EQ( program, glState.currentPipeline ); } #if defined( LOG_GLSL_UNIFORMS ) @@ -1270,7 +1549,18 @@ class GLUniformMatrix4fv : protected GLUniform return; } - glUniformMatrix4fv( p->uniformLocations[ _locationIndex ], numMatrices, transpose, &m[ 0 ][ 0 ] ); + if ( glConfig2.separateShaderObjectsAvailable ) { + for ( int i = 0; i < 3; i++ ) { + GLShader::UniformData* p = _shader->GetUniformData( i ); + if ( !p->program ) { + continue; + } + glProgramUniformMatrix4fv( p->program, p->uniformLocations[_locationIndex], numMatrices, transpose, &m[0][0] ); + } + } else { + GLShader::UniformData* p = _shader->GetUniformData(); + glUniformMatrix4fv( p->uniformLocations[_locationIndex], numMatrices, transpose, &m[0][0] ); + } } public: @@ -1287,16 +1577,14 @@ class GLUniformMatrix34fv : protected GLUniform { protected: GLUniformMatrix34fv( GLShader *shader, const char *name, const int size ) : - GLUniform( shader, name, "mat3x4", 12, 4, false, size ) - { + GLUniform( shader, name, "mat3x4", 12, 4, false, size ) { } - inline void SetValue( int numMatrices, GLboolean transpose, const float *m ) - { - shaderProgram_t *p = _shader->GetProgram(); + inline void SetValue( int numMatrices, GLboolean transpose, const float *m ) { + GLuint program = _shader->GetProgram(); - if ( _global || !_shader->UseMaterialSystem() ) { - ASSERT_EQ( p, glState.currentProgram ); + if ( !glConfig2.separateShaderObjectsAvailable && ( _global || !_shader->UseMaterialSystem() ) ) { + ASSERT_EQ( program, glState.currentPipeline ); } #if defined( LOG_GLSL_UNIFORMS ) @@ -1312,7 +1600,18 @@ class GLUniformMatrix34fv : protected GLUniform return; } - glUniformMatrix3x4fv( p->uniformLocations[ _locationIndex ], numMatrices, transpose, m ); + if ( glConfig2.separateShaderObjectsAvailable ) { + for ( int i = 0; i < 3; i++ ) { + GLShader::UniformData* p = _shader->GetUniformData( i ); + if ( !p->program ) { + continue; + } + glProgramUniformMatrix3x4fv( p->program, p->uniformLocations[_locationIndex], numMatrices, transpose, m ); + } + } else { + GLShader::UniformData* p = _shader->GetUniformData(); + glUniformMatrix3x4fv( p->uniformLocations[_locationIndex], numMatrices, transpose, m ); + } } public: @@ -1351,16 +1650,16 @@ class GLUniformBlock return _name.c_str(); } - void UpdateShaderProgramUniformBlockIndex( shaderProgram_t *shaderProgram ) + void UpdateShaderProgramUniformBlockIndex( ShaderProgramDescriptor* shaderProgram ) { - shaderProgram->uniformBlockIndexes[ _locationIndex ] = glGetUniformBlockIndex( shaderProgram->program, GetName() ); + shaderProgram->uniformBlockIndexes[_locationIndex] = glGetUniformBlockIndex( shaderProgram->id, GetName() ); } void SetBuffer( GLuint buffer ) { - shaderProgram_t *p = _shader->GetProgram(); - GLuint blockIndex = p->uniformBlockIndexes[ _locationIndex ]; + GLuint p = _shader->GetProgram(); + GLuint blockIndex = _shader->GetUniformData( 1 )->uniformBlockIndexes[_locationIndex]; - ASSERT_EQ(p, glState.currentProgram); + // ASSERT_EQ( p, glState.currentPipeline ); if( blockIndex != GL_INVALID_INDEX ) { glBindBufferBase( GL_UNIFORM_BUFFER, blockIndex, buffer ); @@ -1640,8 +1939,15 @@ class GLCompileMacro }; public: + enum ShaderType { + VERTEX = BIT( 0 ), + FRAGMENT = BIT( 1 ), + COMPUTE = BIT( 2 ) + }; + virtual const char *GetName() const = 0; virtual EGLCompileMacro GetType() const = 0; + virtual int GetShaderTypes() const = 0; virtual bool HasConflictingMacros( size_t, const std::vector& ) const { @@ -1703,6 +2009,10 @@ class GLCompileMacro_USE_BSP_SURFACE : return EGLCompileMacro::USE_BSP_SURFACE; } + int GetShaderTypes() const override { + return ShaderType::VERTEX | ShaderType::FRAGMENT; + } + void SetBspSurface( bool enable ) { SetMacro( enable ); @@ -1728,6 +2038,10 @@ class GLCompileMacro_USE_VERTEX_SKINNING : return EGLCompileMacro::USE_VERTEX_SKINNING; } + int GetShaderTypes() const override { + return ShaderType::VERTEX; + } + bool HasConflictingMacros( size_t permutation, const std::vector< GLCompileMacro * > ¯os ) const override; bool MissesRequiredMacros( size_t permutation, const std::vector< GLCompileMacro * > ¯os ) const override; @@ -1761,6 +2075,10 @@ class GLCompileMacro_USE_VERTEX_ANIMATION : return EGLCompileMacro::USE_VERTEX_ANIMATION; } + int GetShaderTypes() const override { + return ShaderType::VERTEX; + } + bool HasConflictingMacros( size_t permutation, const std::vector< GLCompileMacro * > ¯os ) const override; uint32_t GetRequiredVertexAttributes() const override; @@ -1789,6 +2107,10 @@ class GLCompileMacro_USE_TCGEN_ENVIRONMENT : return EGLCompileMacro::USE_TCGEN_ENVIRONMENT; } + int GetShaderTypes() const override { + return ShaderType::VERTEX; + } + bool HasConflictingMacros(size_t permutation, const std::vector< GLCompileMacro * > ¯os) const override; uint32_t GetRequiredVertexAttributes() const override { @@ -1821,6 +2143,10 @@ class GLCompileMacro_USE_TCGEN_LIGHTMAP : return EGLCompileMacro::USE_TCGEN_LIGHTMAP; } + int GetShaderTypes() const override { + return ShaderType::VERTEX; + } + void SetTCGenLightmap( bool enable ) { SetMacro( enable ); @@ -1848,6 +2174,10 @@ class GLCompileMacro_USE_GRID_LIGHTING : return EGLCompileMacro::USE_GRID_LIGHTING; } + int GetShaderTypes() const override { + return ShaderType::VERTEX | ShaderType::FRAGMENT; + } + void SetGridLighting( bool enable ) { SetMacro( enable ); @@ -1875,6 +2205,10 @@ class GLCompileMacro_USE_DELUXE_MAPPING : return EGLCompileMacro::USE_DELUXE_MAPPING; } + int GetShaderTypes() const override { + return ShaderType::VERTEX | ShaderType::FRAGMENT; + } + void SetDeluxeMapping( bool enable ) { SetMacro( enable ); @@ -1902,6 +2236,10 @@ class GLCompileMacro_USE_GRID_DELUXE_MAPPING : return EGLCompileMacro::USE_GRID_DELUXE_MAPPING; } + int GetShaderTypes() const override { + return ShaderType::FRAGMENT; + } + void SetGridDeluxeMapping( bool enable ) { SetMacro( enable ); @@ -1927,6 +2265,10 @@ class GLCompileMacro_USE_HEIGHTMAP_IN_NORMALMAP : return EGLCompileMacro::USE_HEIGHTMAP_IN_NORMALMAP; } + int GetShaderTypes() const override { + return ShaderType::FRAGMENT; + } + void SetHeightMapInNormalMap( bool enable ) { SetMacro( enable ); @@ -1952,6 +2294,10 @@ class GLCompileMacro_USE_RELIEF_MAPPING : return EGLCompileMacro::USE_RELIEF_MAPPING; } + int GetShaderTypes() const override { + return ShaderType::FRAGMENT; + } + void SetReliefMapping( bool enable ) { SetMacro( enable ); @@ -1979,6 +2325,10 @@ class GLCompileMacro_USE_REFLECTIVE_SPECULAR : return EGLCompileMacro::USE_REFLECTIVE_SPECULAR; } + int GetShaderTypes() const override { + return ShaderType::FRAGMENT; + } + void SetReflectiveSpecular( bool enable ) { SetMacro( enable ); @@ -2004,6 +2354,10 @@ class GLCompileMacro_LIGHT_DIRECTIONAL : return EGLCompileMacro::LIGHT_DIRECTIONAL; } + int GetShaderTypes() const override { + return ShaderType::VERTEX | ShaderType::FRAGMENT; + } + void SetMacro_LIGHT_DIRECTIONAL( bool enable ) { SetMacro( enable ); @@ -2029,6 +2383,10 @@ class GLCompileMacro_USE_SHADOWING : return EGLCompileMacro::USE_SHADOWING; } + int GetShaderTypes() const override { + return ShaderType::FRAGMENT; + } + void SetShadowing( bool enable ) { SetMacro( enable ); @@ -2054,6 +2412,10 @@ class GLCompileMacro_USE_DEPTH_FADE : return EGLCompileMacro::USE_DEPTH_FADE; } + int GetShaderTypes() const override { + return ShaderType::VERTEX | ShaderType::FRAGMENT; + } + void SetDepthFade( bool enable ) { SetMacro( enable ); @@ -2079,6 +2441,10 @@ class GLCompileMacro_USE_PHYSICAL_MAPPING : return USE_PHYSICAL_MAPPING; } + int GetShaderTypes() const override { + return ShaderType::FRAGMENT; + } + void SetPhysicalShading( bool enable ) { SetMacro( enable ); @@ -3958,7 +4324,7 @@ class GLShader_generic : { public: GLShader_generic( GLShaderManager *manager ); - void SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; class GLShader_genericMaterial : @@ -3984,7 +4350,7 @@ class GLShader_genericMaterial : public GLCompileMacro_USE_DEPTH_FADE { public: GLShader_genericMaterial( GLShaderManager* manager ); - void SetShaderProgramUniforms( shaderProgram_t* shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor* shaderProgram ) override; }; class GLShader_lightMapping : @@ -4035,7 +4401,7 @@ class GLShader_lightMapping : { public: GLShader_lightMapping( GLShaderManager *manager ); - void SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; class GLShader_lightMappingMaterial : @@ -4083,7 +4449,7 @@ class GLShader_lightMappingMaterial : public GLCompileMacro_USE_PHYSICAL_MAPPING { public: GLShader_lightMappingMaterial( GLShaderManager* manager ); - void SetShaderProgramUniforms( shaderProgram_t* shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor* shaderProgram ) override; }; class GLShader_forwardLighting_omniXYZ : @@ -4126,7 +4492,7 @@ class GLShader_forwardLighting_omniXYZ : { public: GLShader_forwardLighting_omniXYZ( GLShaderManager *manager ); - void SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; class GLShader_forwardLighting_projXYZ : @@ -4171,7 +4537,7 @@ class GLShader_forwardLighting_projXYZ : public: GLShader_forwardLighting_projXYZ( GLShaderManager *manager ); void BuildShaderCompileMacros( std::string& compileMacros ) override; - void SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; class GLShader_forwardLighting_directionalSun : @@ -4223,7 +4589,7 @@ class GLShader_forwardLighting_directionalSun : public: GLShader_forwardLighting_directionalSun( GLShaderManager *manager ); void BuildShaderCompileMacros( std::string& compileMacros ) override; - void SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; class GLShader_shadowFill : @@ -4245,7 +4611,7 @@ class GLShader_shadowFill : { public: GLShader_shadowFill( GLShaderManager *manager ); - void SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; class GLShader_reflection : @@ -4271,7 +4637,7 @@ class GLShader_reflection : { public: GLShader_reflection( GLShaderManager *manager ); - void SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; class GLShader_reflectionMaterial : @@ -4292,7 +4658,7 @@ class GLShader_reflectionMaterial : public GLCompileMacro_USE_RELIEF_MAPPING { public: GLShader_reflectionMaterial( GLShaderManager* manager ); - void SetShaderProgramUniforms( shaderProgram_t* shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor* shaderProgram ) override; }; class GLShader_skybox : @@ -4307,7 +4673,7 @@ class GLShader_skybox : { public: GLShader_skybox( GLShaderManager *manager ); - void SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; class GLShader_skyboxMaterial : @@ -4321,7 +4687,7 @@ class GLShader_skyboxMaterial : public u_ModelViewProjectionMatrix { public: GLShader_skyboxMaterial( GLShaderManager* manager ); - void SetShaderProgramUniforms( shaderProgram_t* shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor* shaderProgram ) override; }; class GLShader_fogQuake3 : @@ -4341,7 +4707,7 @@ class GLShader_fogQuake3 : { public: GLShader_fogQuake3( GLShaderManager *manager ); - void SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; class GLShader_fogQuake3Material : @@ -4356,7 +4722,7 @@ class GLShader_fogQuake3Material : public GLDeformStage { public: GLShader_fogQuake3Material( GLShaderManager* manager ); - void SetShaderProgramUniforms( shaderProgram_t* shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor* shaderProgram ) override; }; class GLShader_fogGlobal : @@ -4370,7 +4736,7 @@ class GLShader_fogGlobal : { public: GLShader_fogGlobal( GLShaderManager *manager ); - void SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; class GLShader_heatHaze : @@ -4392,7 +4758,7 @@ class GLShader_heatHaze : { public: GLShader_heatHaze( GLShaderManager *manager ); - void SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; class GLShader_heatHazeMaterial : @@ -4411,7 +4777,7 @@ class GLShader_heatHazeMaterial : { public: GLShader_heatHazeMaterial( GLShaderManager* manager ); - void SetShaderProgramUniforms( shaderProgram_t* shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor* shaderProgram ) override; }; class GLShader_screen : @@ -4421,7 +4787,7 @@ class GLShader_screen : { public: GLShader_screen( GLShaderManager *manager ); - void SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; class GLShader_screenMaterial : @@ -4430,7 +4796,7 @@ class GLShader_screenMaterial : public u_ModelViewProjectionMatrix { public: GLShader_screenMaterial( GLShaderManager* manager ); - void SetShaderProgramUniforms( shaderProgram_t* shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor* shaderProgram ) override; }; class GLShader_portal : @@ -4442,7 +4808,7 @@ class GLShader_portal : { public: GLShader_portal( GLShaderManager *manager ); - void SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; class GLShader_contrast : @@ -4452,7 +4818,7 @@ class GLShader_contrast : { public: GLShader_contrast( GLShaderManager *manager ); - void SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; class GLShader_cameraEffects : @@ -4469,7 +4835,7 @@ class GLShader_cameraEffects : { public: GLShader_cameraEffects( GLShaderManager *manager ); - void SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; class GLShader_blur : @@ -4482,7 +4848,7 @@ class GLShader_blur : { public: GLShader_blur( GLShaderManager *manager ); - void SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; class GLShader_debugShadowMap : @@ -4492,7 +4858,7 @@ class GLShader_debugShadowMap : { public: GLShader_debugShadowMap( GLShaderManager *manager ); - void SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; class GLShader_liquid : @@ -4528,7 +4894,7 @@ class GLShader_liquid : { public: GLShader_liquid( GLShaderManager *manager ); - void SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; class GLShader_liquidMaterial : @@ -4564,7 +4930,7 @@ class GLShader_liquidMaterial : public GLCompileMacro_USE_RELIEF_MAPPING { public: GLShader_liquidMaterial( GLShaderManager* manager ); - void SetShaderProgramUniforms( shaderProgram_t* shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor* shaderProgram ) override; }; class GLShader_motionblur : @@ -4576,7 +4942,7 @@ class GLShader_motionblur : { public: GLShader_motionblur( GLShaderManager *manager ); - void SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; class GLShader_ssao : @@ -4588,7 +4954,7 @@ class GLShader_ssao : { public: GLShader_ssao( GLShaderManager *manager ); - void SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; class GLShader_depthtile1 : @@ -4599,7 +4965,7 @@ class GLShader_depthtile1 : { public: GLShader_depthtile1( GLShaderManager *manager ); - void SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; class GLShader_depthtile2 : @@ -4609,7 +4975,7 @@ class GLShader_depthtile2 : { public: GLShader_depthtile2( GLShaderManager *manager ); - void SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; class GLShader_lighttile : @@ -4623,7 +4989,7 @@ class GLShader_lighttile : { public: GLShader_lighttile( GLShaderManager *manager ); - void SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; class GLShader_fxaa : @@ -4633,7 +4999,7 @@ class GLShader_fxaa : { public: GLShader_fxaa( GLShaderManager *manager ); - void SetShaderProgramUniforms( shaderProgram_t *shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor *shaderProgram ) override; }; class GLShader_cull : @@ -4664,7 +5030,7 @@ class GLShader_depthReduction : public u_InitialDepthLevel { public: GLShader_depthReduction( GLShaderManager* manager ); - void SetShaderProgramUniforms( shaderProgram_t* shaderProgram ) override; + void SetShaderProgramUniforms( ShaderProgramDescriptor* shaderProgram ) override; }; class GLShader_clearSurfaces : diff --git a/src/engine/renderer/glsl_source/cull_cp.glsl b/src/engine/renderer/glsl_source/cull_cp.glsl index 1e210e21fc..201cdc2844 100644 --- a/src/engine/renderer/glsl_source/cull_cp.glsl +++ b/src/engine/renderer/glsl_source/cull_cp.glsl @@ -42,6 +42,11 @@ layout (local_size_x = 64, local_size_y = 1, local_size_z = 1) in; layout(binding = 0) uniform sampler2D depthImage; +struct SurfaceDescriptor { + BoundingSphere boundingSphere; + uint surfaceCommandIDs[MAX_SURFACE_COMMANDS]; +}; + layout(std430, binding = BIND_SURFACE_DESCRIPTORS) readonly restrict buffer surfaceDescriptorsSSBO { SurfaceDescriptor surfaces[]; }; diff --git a/src/engine/renderer/glsl_source/fogQuake3_vp.glsl b/src/engine/renderer/glsl_source/fogQuake3_vp.glsl index 35123a2d5d..1101a3ad77 100644 --- a/src/engine/renderer/glsl_source/fogQuake3_vp.glsl +++ b/src/engine/renderer/glsl_source/fogQuake3_vp.glsl @@ -44,9 +44,9 @@ void DeformVertex( inout vec4 pos, inout vec3 normal, inout vec2 st, inout vec4 color, - in float time); + in float time ); -void main() +void main() { #insert material_vp @@ -63,7 +63,7 @@ void main() LB.normal, texCoord, color, - u_Time); + u_Time ); // transform vertex position into homogenous clip-space gl_Position = u_ModelViewProjectionMatrix * position; diff --git a/src/engine/renderer/glsl_source/generic_vp.glsl b/src/engine/renderer/glsl_source/generic_vp.glsl index 3affc9a91d..a13740611c 100644 --- a/src/engine/renderer/glsl_source/generic_vp.glsl +++ b/src/engine/renderer/glsl_source/generic_vp.glsl @@ -55,9 +55,9 @@ void DeformVertex( inout vec4 pos, inout vec3 normal, inout vec2 st, inout vec4 color, - in float time); + in float time ); -void main() +void main() { #insert material_vp @@ -72,11 +72,7 @@ void main() color = color * ColorModulateToColor( u_ColorModulateColorGen, lightFactor ) + unpackUnorm4x8( u_Color ) * vec4( lightFactor, lightFactor, lightFactor, 1.0 ); - DeformVertex( position, - LB.normal, - texCoord, - color, - u_Time); + DeformVertex( position, LB.normal, texCoord, color, u_Time ); // transform vertex position into homogenous clip-space gl_Position = u_ModelViewProjectionMatrix * position; diff --git a/src/engine/renderer/glsl_source/lightMapping_vp.glsl b/src/engine/renderer/glsl_source/lightMapping_vp.glsl index 49bee16a28..8e6bf7e30c 100644 --- a/src/engine/renderer/glsl_source/lightMapping_vp.glsl +++ b/src/engine/renderer/glsl_source/lightMapping_vp.glsl @@ -64,7 +64,7 @@ OUT(smooth) vec3 var_Normal; OUT(smooth) vec4 var_Color; -void DeformVertex(inout vec4 pos, inout vec3 normal, inout vec2 st, inout vec4 color, in float time); +void DeformVertex( inout vec4 pos, inout vec3 normal, inout vec2 st, inout vec4 color, in float time ); void main() { @@ -78,7 +78,7 @@ void main() color = color * ColorModulateToColor( u_ColorModulateColorGen ) + unpackUnorm4x8( u_Color ); - DeformVertex(position, LB.normal, texCoord, color, u_Time); + DeformVertex( position, LB.normal, texCoord, color, u_Time ); // transform vertex position into homogenous clip-space gl_Position = u_ModelViewProjectionMatrix * position; diff --git a/src/engine/renderer/glsl_source/material_cp.glsl b/src/engine/renderer/glsl_source/material_cp.glsl index 8156273bd8..159b314988 100644 --- a/src/engine/renderer/glsl_source/material_cp.glsl +++ b/src/engine/renderer/glsl_source/material_cp.glsl @@ -39,10 +39,10 @@ struct BoundingSphere { float radius; }; -struct SurfaceDescriptor { +/* struct SurfaceDescriptor { BoundingSphere boundingSphere; uint surfaceCommandIDs[MAX_SURFACE_COMMANDS]; -}; +}; */ struct PortalSurface { BoundingSphere boundingSphere; diff --git a/src/engine/renderer/tr_backend.cpp b/src/engine/renderer/tr_backend.cpp index 133f2dfba6..d0f882a4b8 100644 --- a/src/engine/renderer/tr_backend.cpp +++ b/src/engine/renderer/tr_backend.cpp @@ -120,32 +120,36 @@ GLuint64 BindAnimatedImage( int unit, const textureBundle_t *bundle ) return GL_BindToTMU( unit, bundle->image[ index ] ); } -void GL_BindProgram( shaderProgram_t *program ) -{ - if ( !program ) - { +void GL_BindProgram( GLuint pipeline, bool override ) { + if ( !pipeline ) { GL_BindNullProgram(); return; } - if ( glState.currentProgram != program ) - { - glUseProgram( program->program ); - glState.currentProgram = program; + if ( glState.currentPipeline != pipeline ) { + if ( glConfig2.separateShaderObjectsAvailable && !override ) { + glBindProgramPipeline( pipeline ); + } else { + glUseProgram( pipeline ); + } + + glState.currentPipeline = pipeline; } } -void GL_BindNullProgram() -{ - if ( r_logFile->integer ) - { +void GL_BindNullProgram( bool override ) { + if ( r_logFile->integer ) { GLimp_LogComment( "--- GL_BindNullProgram ---\n" ); } - if ( glState.currentProgram ) - { - glUseProgram( 0 ); - glState.currentProgram = nullptr; + if ( glState.currentPipeline ) { + if ( glConfig2.separateShaderObjectsAvailable && !override ) { + glBindProgramPipeline( 0 ); + } else { + glUseProgram( 0 ); + } + + glState.currentPipeline = 0; } } @@ -1378,7 +1382,7 @@ static void RB_SetupLightForShadowing( trRefLight_t *light, int index, bool shadowClip ) { // HACK: bring OpenGL into a safe state or strange FBO update problems will occur - GL_BindProgram( nullptr ); + GL_BindNullProgram(); GL_State( GLS_DEFAULT ); GL_Bind( tr.whiteImage ); diff --git a/src/engine/renderer/tr_bsp.cpp b/src/engine/renderer/tr_bsp.cpp index ad2cf25bfa..5db68cc36b 100644 --- a/src/engine/renderer/tr_bsp.cpp +++ b/src/engine/renderer/tr_bsp.cpp @@ -5081,6 +5081,7 @@ void RE_LoadWorldMap( const char *name ) Q_strncpyz( s_worldData.baseName, COM_SkipPath( s_worldData.name ), sizeof( s_worldData.name ) ); COM_StripExtension3( s_worldData.baseName, s_worldData.baseName, sizeof( s_worldData.baseName ) ); + tr.loadingMap = s_worldData.baseName; startMarker = (byte*) ri.Hunk_Alloc( 0, ha_pref::h_low ); @@ -5239,6 +5240,7 @@ void RE_LoadWorldMap( const char *name ) } tr.worldLoaded = true; + tr.loadingMap = ""; GLSL_InitWorldShaders(); if ( glConfig2.reflectionMappingAvailable ) { diff --git a/src/engine/renderer/tr_init.cpp b/src/engine/renderer/tr_init.cpp index 7156dcf52d..446a7d05f6 100644 --- a/src/engine/renderer/tr_init.cpp +++ b/src/engine/renderer/tr_init.cpp @@ -874,7 +874,7 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p glState.vertexAttribsState = 0; glState.vertexAttribPointersSet = 0; - GL_BindProgram( nullptr ); + GL_BindNullProgram(); glBindBuffer( GL_ARRAY_BUFFER, 0 ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, 0 ); @@ -1137,7 +1137,7 @@ ScreenshotCmd screenshotPNGRegistration("screenshotPNG", ssFormat_t::SSF_PNG, "p } int deformIndex = - gl_shaderManager.getDeformShaderIndex( shader.deforms, shader.numDeforms ); + gl_shaderManager.GetDeformShaderIndex( shader.deforms, shader.numDeforms ); for ( shaderStage_t *stage = shader.stages; stage != shader.lastStage; stage++ ) { diff --git a/src/engine/renderer/tr_local.h b/src/engine/renderer/tr_local.h index ed59f14404..4f1c5232f1 100644 --- a/src/engine/renderer/tr_local.h +++ b/src/engine/renderer/tr_local.h @@ -1415,18 +1415,8 @@ enum class shaderProfilerRenderSubGroupsMode { }; // *INDENT-ON* - -// Tr3B - shaderProgram_t represents a pair of one -// GLSL vertex and one GLSL fragment shader - struct shaderProgram_t - { - GLuint program; - GLuint VS, FS, CS; - uint32_t attribs; // vertex array attributes - GLint *uniformLocations; - GLuint *uniformBlockIndexes; - byte *uniformFirewall; - }; + struct ShaderProgramDescriptor; + struct ShaderPipelineDescriptor; // trRefdef_t holds everything that comes in refdef_t, // as well as the locally generated scene information @@ -2439,7 +2429,7 @@ enum class shaderProfilerRenderSubGroupsMode { float vertexAttribsInterpolation; // 0 = no interpolation, 1 = final position uint32_t vertexAttribsNewFrame; // offset for VBO vertex animations uint32_t vertexAttribsOldFrame; // offset for VBO vertex animations - shaderProgram_t *currentProgram; + GLuint currentPipeline; FBO_t *currentFBO; VBO_t *currentVBO; IBO_t *currentIBO; @@ -2723,6 +2713,7 @@ enum class shaderProfilerRenderSubGroupsMode { bool worldLoaded; world_t *world; + std::string loadingMap; TextureManager textureManager; @@ -3239,10 +3230,10 @@ inline bool checkGLErrors() void GL_BindNearestCubeMap( int unit, const vec3_t xyz ); void GL_Unbind( image_t *image ); GLuint64 BindAnimatedImage( int unit, const textureBundle_t *bundle ); - void GL_TextureFilter( image_t *image, filterType_t filterType ); - void GL_BindProgram( shaderProgram_t *program ); GLuint64 GL_BindToTMU( int unit, image_t *image ); - void GL_BindNullProgram(); + void GL_TextureFilter( image_t *image, filterType_t filterType ); + void GL_BindProgram( GLuint pipeline, bool override = false ); + void GL_BindNullProgram( bool override = false); void GL_SetDefaultState(); void GL_SelectTexture( int unit ); void GL_TextureMode( const char *string ); diff --git a/src/engine/renderer/tr_main.cpp b/src/engine/renderer/tr_main.cpp index 2c8ac3d501..639226424a 100644 --- a/src/engine/renderer/tr_main.cpp +++ b/src/engine/renderer/tr_main.cpp @@ -2469,7 +2469,7 @@ static void R_DebugGraphics() // the render thread can't make callbacks to the main thread R_SyncRenderThread(); - GL_BindProgram( nullptr ); + GL_BindNullProgram(); GL_Bind( tr.whiteImage ); diff --git a/src/engine/renderer/tr_public.h b/src/engine/renderer/tr_public.h index e417473e89..4559fabc76 100644 --- a/src/engine/renderer/tr_public.h +++ b/src/engine/renderer/tr_public.h @@ -93,6 +93,7 @@ struct glconfig2_t int textureRGBA16BlendAvailable; bool textureIntegerAvailable; bool textureRGAvailable; + bool separateShaderObjectsAvailable; bool computeShaderAvailable; bool bindlessTexturesAvailable; // do the driver/hardware support it bool usingBindlessTextures; // are we using them right now diff --git a/src/engine/renderer/tr_shade.cpp b/src/engine/renderer/tr_shade.cpp index 19dd45a2fc..3536d27b75 100644 --- a/src/engine/renderer/tr_shade.cpp +++ b/src/engine/renderer/tr_shade.cpp @@ -191,7 +191,7 @@ void GLSL_InitWorldShaders() { // Material system shaders that are always loaded if material system is available if ( glConfig2.usingMaterialSystem ) { - gl_shaderManager.load( gl_cullShader ); + gl_shaderManager.LoadShader( gl_cullShader ); } } @@ -211,20 +211,20 @@ static void GLSL_InitGPUShadersOrError() gl_shaderManager.GenerateBuiltinHeaders(); // single texture rendering - gl_shaderManager.load( gl_genericShader ); + gl_shaderManager.LoadShader( gl_genericShader ); // standard light mapping - gl_shaderManager.load( gl_lightMappingShader ); + gl_shaderManager.LoadShader( gl_lightMappingShader ); // Material system shaders that are always loaded if material system is available if ( glConfig2.usingMaterialSystem ) { - gl_shaderManager.load( gl_genericShaderMaterial ); - gl_shaderManager.load( gl_lightMappingShaderMaterial ); + gl_shaderManager.LoadShader( gl_genericShaderMaterial ); + gl_shaderManager.LoadShader( gl_lightMappingShaderMaterial ); - gl_shaderManager.load( gl_clearSurfacesShader ); - gl_shaderManager.load( gl_processSurfacesShader ); - gl_shaderManager.load( gl_depthReductionShader ); + gl_shaderManager.LoadShader( gl_clearSurfacesShader ); + gl_shaderManager.LoadShader( gl_processSurfacesShader ); + gl_shaderManager.LoadShader( gl_depthReductionShader ); } if ( tr.world ) // this only happens with /glsl_restart @@ -240,18 +240,18 @@ static void GLSL_InitGPUShadersOrError() { case realtimeLightingRenderer_t::LEGACY: // projective lighting ( Doom3 style ) - gl_shaderManager.load( gl_forwardLightingShader_projXYZ ); + gl_shaderManager.LoadShader( gl_forwardLightingShader_projXYZ ); // omni-directional specular bump mapping ( Doom3 style ) - gl_shaderManager.load( gl_forwardLightingShader_omniXYZ ); + gl_shaderManager.LoadShader( gl_forwardLightingShader_omniXYZ ); // directional sun lighting ( Doom3 style ) - gl_shaderManager.load( gl_forwardLightingShader_directionalSun ); + gl_shaderManager.LoadShader( gl_forwardLightingShader_directionalSun ); break; case realtimeLightingRenderer_t::TILED: - gl_shaderManager.load( gl_depthtile1Shader ); - gl_shaderManager.load( gl_depthtile2Shader ); - gl_shaderManager.load( gl_lighttileShader ); + gl_shaderManager.LoadShader( gl_depthtile1Shader ); + gl_shaderManager.LoadShader( gl_depthtile2Shader ); + gl_shaderManager.LoadShader( gl_lighttileShader ); DAEMON_FALLTHROUGH; default: /* Dynamic shadowing code also needs this shader. @@ -266,7 +266,7 @@ static void GLSL_InitGPUShadersOrError() if ( glConfig2.shadowMapping ) { // projective lighting ( Doom3 style ) - gl_shaderManager.load( gl_forwardLightingShader_projXYZ ); + gl_shaderManager.LoadShader( gl_forwardLightingShader_projXYZ ); } } } @@ -274,106 +274,106 @@ static void GLSL_InitGPUShadersOrError() if ( glConfig2.reflectionMappingAvailable ) { // bumped cubemap reflection for abitrary polygons ( EMBM ) - gl_shaderManager.load( gl_reflectionShader ); + gl_shaderManager.LoadShader( gl_reflectionShader ); if ( glConfig2.usingMaterialSystem ) { - gl_shaderManager.load( gl_reflectionShaderMaterial ); + gl_shaderManager.LoadShader( gl_reflectionShaderMaterial ); } } if ( r_drawSky.Get() ) { // skybox drawing for abitrary polygons - gl_shaderManager.load( gl_skyboxShader ); + gl_shaderManager.LoadShader( gl_skyboxShader ); if ( glConfig2.usingMaterialSystem ) { - gl_shaderManager.load( gl_skyboxShaderMaterial ); + gl_shaderManager.LoadShader( gl_skyboxShaderMaterial ); } } // Fog GLSL is always loaded and built because disabling fog is cheat. { // Q3A volumetric fog - gl_shaderManager.load( gl_fogQuake3Shader ); + gl_shaderManager.LoadShader( gl_fogQuake3Shader ); if ( glConfig2.usingMaterialSystem ) { - gl_shaderManager.load( gl_fogQuake3ShaderMaterial ); + gl_shaderManager.LoadShader( gl_fogQuake3ShaderMaterial ); } // global fog post process effect - gl_shaderManager.load( gl_fogGlobalShader ); + gl_shaderManager.LoadShader( gl_fogGlobalShader ); } if ( r_heatHaze->integer ) { // heatHaze post process effect - gl_shaderManager.load( gl_heatHazeShader ); + gl_shaderManager.LoadShader( gl_heatHazeShader ); if ( glConfig2.usingMaterialSystem ) { - gl_shaderManager.load( gl_heatHazeShaderMaterial ); + gl_shaderManager.LoadShader( gl_heatHazeShaderMaterial ); } } if ( glConfig2.bloom ) { // screen post process effect - gl_shaderManager.load( gl_screenShader ); + gl_shaderManager.LoadShader( gl_screenShader ); if ( glConfig2.usingMaterialSystem ) { - gl_shaderManager.load( gl_screenShaderMaterial ); + gl_shaderManager.LoadShader( gl_screenShaderMaterial ); } // LDR bright pass filter - gl_shaderManager.load( gl_contrastShader ); + gl_shaderManager.LoadShader( gl_contrastShader ); } // portal process effect - gl_shaderManager.load( gl_portalShader ); + gl_shaderManager.LoadShader( gl_portalShader ); // camera post process effect - gl_shaderManager.load( gl_cameraEffectsShader ); + gl_shaderManager.LoadShader( gl_cameraEffectsShader ); if ( glConfig2.bloom || glConfig2.shadowMapping ) { // gaussian blur - gl_shaderManager.load( gl_blurShader ); + gl_shaderManager.LoadShader( gl_blurShader ); } if ( glConfig2.shadowMapping ) { // shadowmap distance compression - gl_shaderManager.load( gl_shadowFillShader ); + gl_shaderManager.LoadShader( gl_shadowFillShader ); // debug utils - gl_shaderManager.load( gl_debugShadowMapShader ); + gl_shaderManager.LoadShader( gl_debugShadowMapShader ); } if ( r_liquidMapping->integer != 0 ) { - gl_shaderManager.load( gl_liquidShader ); + gl_shaderManager.LoadShader( gl_liquidShader ); if ( glConfig2.usingMaterialSystem ) { - gl_shaderManager.load( gl_liquidShaderMaterial ); + gl_shaderManager.LoadShader( gl_liquidShaderMaterial ); } } if ( glConfig2.motionBlur ) { - gl_shaderManager.load( gl_motionblurShader ); + gl_shaderManager.LoadShader( gl_motionblurShader ); } if ( r_ssao->integer ) { if ( glConfig2.textureGatherAvailable ) { - gl_shaderManager.load( gl_ssaoShader ); + gl_shaderManager.LoadShader( gl_ssaoShader ); } else { @@ -383,12 +383,12 @@ static void GLSL_InitGPUShadersOrError() if ( r_FXAA->integer != 0 ) { - gl_shaderManager.load( gl_fxaaShader ); + gl_shaderManager.LoadShader( gl_fxaaShader ); } if ( r_lazyShaders.Get() == 0 ) { - gl_shaderManager.buildAll(); + gl_shaderManager.BuildAll(); } } @@ -430,7 +430,7 @@ void GLSL_InitGPUShaders() GLSL_InitGPUShadersOrError(); if ( r_lazyShaders.Get() == 1 && tr.world != nullptr ) { - gl_shaderManager.buildAll(); + gl_shaderManager.BuildAll(); } Log::Warn("External shaders in use."); } @@ -465,7 +465,7 @@ void GLSL_ShutdownGPUShaders() { R_SyncRenderThread(); - gl_shaderManager.freeAll(); + gl_shaderManager.FreeAll(); gl_genericShader = nullptr; gl_genericShaderMaterial = nullptr; @@ -511,7 +511,7 @@ void GLSL_FinishGPUShaders() { R_SyncRenderThread(); - gl_shaderManager.buildAll(); + gl_shaderManager.BuildAll(); } /* diff --git a/src/engine/renderer/tr_shader.cpp b/src/engine/renderer/tr_shader.cpp index eeac8658df..65a215295c 100644 --- a/src/engine/renderer/tr_shader.cpp +++ b/src/engine/renderer/tr_shader.cpp @@ -5229,7 +5229,7 @@ static void FinishStages() GroupActiveStages(); int deformIndex = shader.numDeforms > 0 - ? gl_shaderManager.getDeformShaderIndex( shader.deforms, shader.numDeforms ) + ? gl_shaderManager.GetDeformShaderIndex( shader.deforms, shader.numDeforms ) : 0; for ( size_t s = 0; s < numStages; s++ ) diff --git a/src/engine/sys/sdl_glimp.cpp b/src/engine/sys/sdl_glimp.cpp index feae888678..88c77f82ed 100644 --- a/src/engine/sys/sdl_glimp.cpp +++ b/src/engine/sys/sdl_glimp.cpp @@ -90,12 +90,14 @@ static Cvar::Cvar r_arb_map_buffer_range( "r_arb_map_buffer_range", "Use GL_ARB_map_buffer_range if available", Cvar::NONE, true ); static Cvar::Cvar r_arb_multi_draw_indirect( "r_arb_multi_draw_indirect", "Use GL_ARB_multi_draw_indirect if available", Cvar::NONE, true ); -static Cvar::Cvar r_arb_shader_draw_parameters( "r_arb_shader_draw_parameters", - "Use GL_ARB_shader_draw_parameters if available", Cvar::NONE, true ); +static Cvar::Cvar r_arb_separate_shader_objects( "r_arb_separate_shader_objects", + "Use GL_ARB_separate_shader_objects if available", Cvar::NONE, true ); static Cvar::Cvar r_arb_shader_atomic_counters( "r_arb_shader_atomic_counters", "Use GL_ARB_shader_atomic_counters if available", Cvar::NONE, true ); static Cvar::Cvar r_arb_shader_atomic_counter_ops( "r_arb_shader_atomic_counter_ops", "Use GL_ARB_shader_atomic_counter_ops if available", Cvar::NONE, true ); +static Cvar::Cvar r_arb_shader_draw_parameters( "r_arb_shader_draw_parameters", + "Use GL_ARB_shader_draw_parameters if available", Cvar::NONE, true ); static Cvar::Cvar r_arb_shader_image_load_store( "r_arb_shader_image_load_store", "Use GL_ARB_shader_image_load_store if available", Cvar::NONE, true ); static Cvar::Cvar r_arb_shader_storage_buffer_object( "r_arb_shader_storage_buffer_object", @@ -1993,6 +1995,7 @@ static void GLimp_InitExtensions() Cvar::Latch( r_arb_internalformat_query2 ); Cvar::Latch( r_arb_map_buffer_range ); Cvar::Latch( r_arb_multi_draw_indirect ); + Cvar::Latch( r_arb_separate_shader_objects ); Cvar::Latch( r_arb_shader_atomic_counters ); Cvar::Latch( r_arb_shader_atomic_counter_ops ); Cvar::Latch( r_arb_shader_draw_parameters ); @@ -2571,6 +2574,9 @@ static void GLimp_InitExtensions() // made required in OpenGL 4.3 glConfig2.vertexAttribBindingAvailable = LOAD_EXTENSION_WITH_TEST( ExtFlag_NONE, ARB_vertex_attrib_binding, r_arb_vertex_attrib_binding.Get() ); + // made required in OpenGL 4.1 + glConfig2.separateShaderObjectsAvailable = LOAD_EXTENSION_WITH_TEST( ExtFlag_NONE, ARB_separate_shader_objects, r_arb_separate_shader_objects.Get() ); + glConfig2.geometryCacheAvailable = glConfig2.vertexAttribBindingAvailable && glConfig2.directStateAccessAvailable; glConfig2.materialSystemAvailable = glConfig2.shaderDrawParametersAvailable && glConfig2.SSBOAvailable