Beispiel #1
0
	void GLSLProgramObject::Reload(bool reloadFromDisk, bool validate) {
		const auto   oldSrcHash = curSrcHash;
		      bool   oldValid  = IsValid();
		const GLuint oldProgID = objID;

		// reload shader from disk?
		reloadFromDisk = reloadFromDisk || !oldValid || (oldProgID == 0);
		if (reloadFromDisk) {
			bool sourceChanged = false;
			for (IShaderObject*& so: GetAttachedShaderObjs()) {
				sourceChanged |= so->ReloadFromDisk();
			}
		}

		//
		log = "";
		valid = false;

		// create shader source hash
		curFlagsHash = GetHash();
		curSrcHash = curFlagsHash;
		for (const IShaderObject* so: GetAttachedShaderObjs()) {
			curSrcHash ^= so->GetHash();
		}

		// clear all uniform locations
		for (auto& us_pair: uniformStates) {
			us_pair.second.SetLocation(GL_INVALID_INDEX);
		}

		// early-exit: empty program
		// TODO delete existing program if exists?
		if (GetAttachedShaderObjs().empty())
			return;

		// push old program to cache and pop new if available
		const bool useShaderCache = oldValid && configHandler->GetBool("UseShaderCache");
		bool deleteOldShader = true;
		objID = 0;
		if (useShaderCache) {
			CShaderHandler::ShaderCache& shadersCache = shaderHandler->GetShaderCache();
			deleteOldShader = !shadersCache.Push(oldSrcHash, oldProgID);
			objID = shadersCache.Find(curSrcHash);
		}

		// recompile if not found in cache (id 0)
		if (objID == 0) {
			objID = glCreateProgram();

			bool shadersValid = true;
			for (IShaderObject*& so: GetAttachedShaderObjs()) {
				assert(dynamic_cast<GLSLShaderObject*>(so));
				auto gso = static_cast<GLSLShaderObject*>(so);
				auto obj = gso->CompileShaderObject();

				if (obj->valid) {
					glAttachShader(objID, obj->id);
				} else {
					shadersValid = false;
				}
			}
			if (!shadersValid)
				return;

			Link();
		} else {
			valid = true;
		}

		//
		/*
		if (validate) {
			Validate(); //FIXME: fails on ATI, see https://springrts.com/mantis/view.php?id=4715
		}
		*/

		// copy full program state from old to new program (uniforms etc.)
		if (IsValid()) {
			GLSLCopyState(objID, oldValid ? oldProgID : 0, &uniformStates);
		}

		// delete old program when not further used
		if (deleteOldShader)
			glDeleteProgram(oldProgID);
	}
Beispiel #2
0
GLhandleARB        P3DShaderLoader::GetProgramHandle
                                      (bool                HaveDiffuseTex,
                                       bool                HaveNormalMap,
                                       bool                TwoSided) const
 {
  GLhandleARB                          ProgHandle;
  GLhandleARB                          ShaderHandle;
  const GLcharARB                     *SourceStrings[ShaderSrcHeaderLineCount + 1];
  GLint                                LinkStatus;
  bool                                 ShaderOk;

  ProgHandle = FindByProps(HaveDiffuseTex,HaveNormalMap,TwoSided);

  if (ProgHandle != 0)
   {
    return(ProgHandle);
   }

  #ifdef USE_OPENGL_20
  ProgHandle = glCreateProgram();
  #else
  ProgHandle = glCreateProgramObjectARB();
  #endif

  if (ProgHandle != 0)
   {
    SourceStrings[0] = HaveDiffuseTex ? ShaderSrcDefineHaveDiffuseTex :
                                        ShaderSrcEmptyLine;
    SourceStrings[1] = HaveNormalMap  ? ShaderSrcDefineHaveNormalMap  :
                                        ShaderSrcEmptyLine;
    SourceStrings[2] = TwoSided ? ShaderSrcDefineTwoSided :
                                  ShaderSrcEmptyLine;
    SourceStrings[3] = ShaderSrcLineNumberSetup;

    ShaderOk = true;

    if (VertexProgramSrc != 0)
     {
      SourceStrings[ShaderSrcHeaderLineCount] = VertexProgramSrc;

      #ifdef USE_OPENGL_20
      ShaderOk = CompileShaderObject(&ShaderHandle,GL_VERTEX_SHADER,ShaderSrcHeaderLineCount + 1,SourceStrings);
      #else
      ShaderOk = CompileShaderObject(&ShaderHandle,GL_VERTEX_SHADER_ARB,ShaderSrcHeaderLineCount + 1,SourceStrings);
      #endif

      if (ShaderOk)
       {
        #ifdef USE_OPENGL_20
        glAttachShader(ProgHandle,ShaderHandle);
        glDeleteShader(ShaderHandle);
        #else
        glAttachObjectARB(ProgHandle,ShaderHandle);
        glDeleteObjectARB(ShaderHandle);
        #endif
       }
     }

    if (ShaderOk)
     {
      if (FragmentProgramSrc != 0)
       {
        SourceStrings[ShaderSrcHeaderLineCount] = FragmentProgramSrc;

        #ifdef USE_OPENGL_20
        ShaderOk = CompileShaderObject(&ShaderHandle,GL_FRAGMENT_SHADER,ShaderSrcHeaderLineCount + 1,SourceStrings);
        #else
        ShaderOk = CompileShaderObject(&ShaderHandle,GL_FRAGMENT_SHADER_ARB,ShaderSrcHeaderLineCount + 1,SourceStrings);
        #endif

        if (ShaderOk)
         {
          #ifdef USE_OPENGL_20
          glAttachShader(ProgHandle,ShaderHandle);
          glDeleteShader(ShaderHandle);
          #else
          glAttachObjectARB(ProgHandle,ShaderHandle);
          glDeleteObjectARB(ShaderHandle);
          #endif
         }
       }
     }

    if (ShaderOk)
     {
      #ifdef USE_OPENGL_20
      glLinkProgram(ProgHandle);
      #else
      glLinkProgramARB(ProgHandle);
      #endif

      #ifdef USE_OPENGL_20
      glGetProgramiv( ProgHandle,GL_LINK_STATUS,&LinkStatus);
      #else
      glGetObjectParameterivARB( ProgHandle,
                                 GL_OBJECT_LINK_STATUS_ARB,
                                &LinkStatus);
      #endif

      DumpInfoLog(ProgHandle);

      if (LinkStatus)
       {
        GLhandleARB    CurrProgHandle;

        #ifdef USE_OPENGL_20
        glGetIntegerv(GL_CURRENT_PROGRAM,(GLint*)&CurrProgHandle);
        #else
        CurrProgHandle = glGetHandleARB(GL_PROGRAM_OBJECT_ARB);
        #endif

        #ifdef USE_OPENGL_20
        glUseProgram(ProgHandle);
        #else
        glUseProgramObjectARB(ProgHandle);
        #endif

        GLint                    Location;

        #ifdef USE_OPENGL_20
        Location = glGetUniformLocation(ProgHandle,"DiffuseTexSampler");
        #else
        Location = glGetUniformLocationARB(ProgHandle,"DiffuseTexSampler");
        #endif

        if (Location != -1)
         {
          #ifdef USE_OPENGL_20
          glUniform1i(Location,0);
          #else
          glUniform1iARB(Location,0);
          #endif
         }

        #ifdef USE_OPENGL_20
        Location = glGetUniformLocation(ProgHandle,"NormalMapSampler");
        #else
        Location = glGetUniformLocationARB(ProgHandle,"NormalMapSampler");
        #endif

        if (Location != -1)
         {
          #ifdef USE_OPENGL_20
          glUniform1i(Location,1);
          #else
          glUniform1iARB(Location,1);
          #endif
         }

        #ifdef USE_OPENGL_20
        glUseProgram(CurrProgHandle);
        #else
        glUseProgramObjectARB(CurrProgHandle);
        #endif
       }
      else
       {
        fprintf(stderr,"error: shader linkage failed\n");

        #ifdef USE_OPENGL_20
        glDeleteProgram(ProgHandle);
        #else
        glDeleteObjectARB(ProgHandle);
        #endif

        ProgHandle = 0;
       }
     }
    else
     {
      #ifdef USE_OPENGL_20
      glDeleteProgram(ProgHandle);
      #else
      glDeleteObjectARB(ProgHandle);
      #endif

      ProgHandle = 0;
     }
   }
  else
   {
    fprintf(stderr,"error: unable to create GLSL program object\n");
   }

  if (ProgHandle != 0)
   {
    P3DShaderEntry Entry;

    Entry.ProgramHandle  = ProgHandle;
    Entry.HaveDiffuseTex = HaveDiffuseTex;
    Entry.HaveNormalMap  = HaveNormalMap;
    Entry.TwoSided       = TwoSided;

    ShaderSet.push_back(Entry);
   }

  return(ProgHandle);
 }