//-----------------------------------------------------------------------
GLSLLinkProgram::GLSLLinkProgram(GLSLGpuProgram* vertexProgram, GLSLGpuProgram* geometryProgram, GLSLGpuProgram* fragmentProgram)
    : mVertexProgram(vertexProgram)
    , mGeometryProgram(geometryProgram)
    , mFragmentProgram(fragmentProgram)
    , mUniformRefsBuilt(false)
    , mLinked(false)

{
    //checkForGLSLError( "GLSLLinkProgram::GLSLLinkProgram", "Error prior to Creating GLSL Program Object", 0);
    glGetError(); //Clean up the error. Otherwise will flood log.
    mGLHandle = glCreateProgramObjectARB();
    checkForGLSLError( "GLSLLinkProgram::GLSLLinkProgram", "Error Creating GLSL Program Object", 0 );


    // tell shaders to attach themselves to the LinkProgram
    // let the shaders do the attaching since they may have several children to attach
    if (mVertexProgram)
    {
        mVertexProgram->getGLSLProgram()->attachToProgramObject(mGLHandle);
        setSkeletalAnimationIncluded(mVertexProgram->isSkeletalAnimationIncluded());
    }
    if (mGeometryProgram)
    {
        mGeometryProgram->getGLSLProgram()->attachToProgramObject(mGLHandle);
        //Don't set adjacency flag. We handle it internally and expose "false"
    }
    if (mFragmentProgram)
    {
        mFragmentProgram->getGLSLProgram()->attachToProgramObject(mGLHandle);
    }

}
Пример #2
0
	//-----------------------------------------------------------------------
	void GLSLProgram::attachToProgramObject( const GLhandleARB programObject )
	{
		glAttachObjectARB( programObject, mGLHandle );
		checkForGLSLError( "GLSLLinkProgram::GLSLLinkProgram",
			"Error attaching " + mName + " shader object to GLSL Program Object", programObject );
		// attach child objects
		GLSLProgramContainerIterator childprogramcurrent = mAttachedGLSLPrograms.begin();
		GLSLProgramContainerIterator childprogramend = mAttachedGLSLPrograms.end();

 		while (childprogramcurrent != childprogramend)
		{

			GLSLProgram* childShader = *childprogramcurrent;
			// bug in ATI GLSL linker : modules without main function must be recompiled each time 
			// they are linked to a different program object
			// don't check for compile errors since there won't be any
			// *** minor inconvenience until ATI fixes there driver
			childShader->compile(false);

			childShader->attachToProgramObject( programObject );

			++childprogramcurrent;
		}

	}
Пример #3
0
    //-----------------------------------------------------------------------
    void GLSLProgram::loadFromSource(void)
    {
        // only create a shader object if glsl is supported
        if (isSupported())
        {
            checkForGLSLError( "GLSLProgram::GLSLProgram", "GL Errors before creating shader object", 0 );
            // create shader object
            mGLHandle = glCreateShaderObjectARB(
                (mType == GPT_VERTEX_PROGRAM) ? GL_VERTEX_SHADER_ARB : GL_FRAGMENT_SHADER_ARB );

            checkForGLSLError( "GLSLProgram::GLSLProgram", "Error creating GLSL shader Object", 0 );
        }

        const char* SLSource = mSource.c_str();
		glShaderSourceARB(mGLHandle, 1, &SLSource, NULL);
		// check for load errors
		checkForGLSLError( "GLSLProgram::loadFromSource", "Cannot load GLSL high-level shader source : " + mName, 0 );

		compile();
    }
Пример #4
0
    //---------------------------------------------------------------------------
	bool GLSLProgram::compile(const bool checkErrors)
	{

		glCompileShaderARB(mGLHandle);
		// check for compile errors
		glGetObjectParameterivARB(mGLHandle, GL_OBJECT_COMPILE_STATUS_ARB, &mCompiled);
		// force exception if not compiled
		if (checkErrors)
		{
			checkForGLSLError( "GLSLProgram::loadFromSource", "Cannot compile GLSL high-level shader : " + mName + " ", mGLHandle, !mCompiled, !mCompiled );
			
			if (mCompiled)
			{
				logObjectInfo( mName + " : GLSL compiled ", mGLHandle );
			}
		}
		return (mCompiled == 1);

	}
//-----------------------------------------------------------------------
void GLSLLinkProgram::updateUniforms(GpuProgramParametersSharedPtr params,
                                     uint16 mask, GpuProgramType fromProgType)
{
    // iterate through uniform reference list and update uniform values
    GLUniformReferenceIterator currentUniform = mGLUniformReferences.begin();
    GLUniformReferenceIterator endUniform = mGLUniformReferences.end();

    for (; currentUniform != endUniform; ++currentUniform)
    {
        // Only pull values from buffer it's supposed to be in (vertex or fragment)
        // This method will be called twice, once for vertex program params,
        // and once for fragment program params.
        if (fromProgType == currentUniform->mSourceProgType)
        {
            const GpuConstantDefinition* def = currentUniform->mConstantDef;
            if (def->variability & mask)
            {

                GLsizei glArraySize = (GLsizei)def->arraySize;

                // get the index in the parameter real list
                switch (def->constType)
                {
                case GCT_FLOAT1:
                    glUniform1fvARB(currentUniform->mLocation, glArraySize,
                                    params->getFloatPointer(def->physicalIndex));
                    break;
                case GCT_FLOAT2:
                    glUniform2fvARB(currentUniform->mLocation, glArraySize,
                                    params->getFloatPointer(def->physicalIndex));
                    break;
                case GCT_FLOAT3:
                    glUniform3fvARB(currentUniform->mLocation, glArraySize,
                                    params->getFloatPointer(def->physicalIndex));
                    break;
                case GCT_FLOAT4:
                    glUniform4fvARB(currentUniform->mLocation, glArraySize,
                                    params->getFloatPointer(def->physicalIndex));
                    break;
                case GCT_MATRIX_2X2:
                    glUniformMatrix2fvARB(currentUniform->mLocation, glArraySize,
                                          GL_TRUE, params->getFloatPointer(def->physicalIndex));
                    break;
                case GCT_MATRIX_2X3:
                    if (GLEW_VERSION_2_1)
                    {
                        glUniformMatrix2x3fv(currentUniform->mLocation, glArraySize,
                                             GL_TRUE, params->getFloatPointer(def->physicalIndex));
                    }
                    break;
                case GCT_MATRIX_2X4:
                    if (GLEW_VERSION_2_1)
                    {
                        glUniformMatrix2x4fv(currentUniform->mLocation, glArraySize,
                                             GL_TRUE, params->getFloatPointer(def->physicalIndex));
                    }
                    break;
                case GCT_MATRIX_3X2:
                    if (GLEW_VERSION_2_1)
                    {
                        glUniformMatrix3x2fv(currentUniform->mLocation, glArraySize,
                                             GL_TRUE, params->getFloatPointer(def->physicalIndex));
                    }
                    break;
                case GCT_MATRIX_3X3:
                    glUniformMatrix3fvARB(currentUniform->mLocation, glArraySize,
                                          GL_TRUE, params->getFloatPointer(def->physicalIndex));
                    break;
                case GCT_MATRIX_3X4:
                    if (GLEW_VERSION_2_1)
                    {
                        glUniformMatrix3x4fv(currentUniform->mLocation, glArraySize,
                                             GL_TRUE, params->getFloatPointer(def->physicalIndex));
                    }
                    break;
                case GCT_MATRIX_4X2:
                    if (GLEW_VERSION_2_1)
                    {
                        glUniformMatrix4x2fv(currentUniform->mLocation, glArraySize,
                                             GL_TRUE, params->getFloatPointer(def->physicalIndex));
                    }
                    break;
                case GCT_MATRIX_4X3:
                    if (GLEW_VERSION_2_1)
                    {
                        glUniformMatrix4x3fv(currentUniform->mLocation, glArraySize,
                                             GL_TRUE, params->getFloatPointer(def->physicalIndex));
                    }
                    break;
                case GCT_MATRIX_4X4:
                    glUniformMatrix4fvARB(currentUniform->mLocation, glArraySize,
                                          GL_TRUE, params->getFloatPointer(def->physicalIndex));
                    break;
                case GCT_INT1:
                    glUniform1ivARB(currentUniform->mLocation, glArraySize,
                                    (GLint*)params->getIntPointer(def->physicalIndex));
                    break;
                case GCT_INT2:
                    glUniform2ivARB(currentUniform->mLocation, glArraySize,
                                    (GLint*)params->getIntPointer(def->physicalIndex));
                    break;
                case GCT_INT3:
                    glUniform3ivARB(currentUniform->mLocation, glArraySize,
                                    (GLint*)params->getIntPointer(def->physicalIndex));
                    break;
                case GCT_INT4:
                    glUniform4ivARB(currentUniform->mLocation, glArraySize,
                                    (GLint*)params->getIntPointer(def->physicalIndex));
                    break;
                case GCT_SAMPLER1D:
                case GCT_SAMPLER1DSHADOW:
                case GCT_SAMPLER2D:
                case GCT_SAMPLER2DSHADOW:
                case GCT_SAMPLER3D:
                case GCT_SAMPLERCUBE:
                    // samplers handled like 1-element ints
                    glUniform1ivARB(currentUniform->mLocation, 1,
                                    (GLint*)params->getIntPointer(def->physicalIndex));
                    break;
                case GCT_UNKNOWN:
                    break;

                } // end switch
#if OGRE_DEBUG_MODE
                checkForGLSLError( "GLSLLinkProgram::updateUniforms", "Error updating uniform", 0 );
#endif
            } // variability & mask
        } // fromProgType == currentUniform->mSourceProgType

    } // end for
}
//-----------------------------------------------------------------------
void GLSLLinkProgram::activate(void)
{
    if (!mLinked)
    {
        if (mVertexProgram)
        {
            // Some drivers (e.g. OS X on nvidia) incorrectly determine the attribute binding automatically
            // and end up aliasing existing built-ins. So avoid!
            // Bind all used attribs - not all possible ones otherwise we'll get
            // lots of warnings in the log, and also may end up aliasing names used
            // as varyings by accident
            // Because we can't ask GL whether an attribute is used in the shader
            // until it is linked (chicken and egg!) we have to parse the source

            size_t numAttribs = sizeof(msCustomAttributes)/sizeof(CustomAttribute);
            const String& vpSource = mVertexProgram->getGLSLProgram()->getSource();
            for (size_t i = 0; i < numAttribs; ++i)
            {
                const CustomAttribute& a = msCustomAttributes[i];

                // we're looking for either:
                //   attribute vec<n> <semantic_name>
                //   in vec<n> <semantic_name>
                // The latter is recommended in GLSL 1.3 onwards
                // be slightly flexible about formatting
                String::size_type pos = vpSource.find(a.name);
                if (pos != String::npos)
                {
                    String::size_type startpos = vpSource.find("attribute", pos < 20 ? 0 : pos-20);
                    if (startpos == String::npos)
                        startpos = vpSource.find("in", pos-20);
                    if (startpos != String::npos && startpos < pos)
                    {
                        // final check
                        String expr = vpSource.substr(startpos, pos + a.name.length() - startpos);
                        StringVector vec = StringUtil::split(expr);
                        if ((vec[0] == "in" || vec[0] == "attribute") && vec[2] == a.name)
                            glBindAttribLocationARB(mGLHandle, a.attrib, a.name.c_str());
                    }

                }
            }
        }

        if (mGeometryProgram)
        {
            RenderOperation::OperationType inputOperationType = mGeometryProgram->getGLSLProgram()->getInputOperationType();
            glProgramParameteriEXT(mGLHandle,GL_GEOMETRY_INPUT_TYPE_EXT,
                                   getGLGeometryInputPrimitiveType(inputOperationType, mGeometryProgram->isAdjacencyInfoRequired()));

            RenderOperation::OperationType outputOperationType = mGeometryProgram->getGLSLProgram()->getOutputOperationType();
            switch (outputOperationType)
            {
            case RenderOperation::OT_POINT_LIST:
            case RenderOperation::OT_LINE_STRIP:
            case RenderOperation::OT_TRIANGLE_STRIP:
            case RenderOperation::OT_LINE_LIST:
            case RenderOperation::OT_TRIANGLE_LIST:
            case RenderOperation::OT_TRIANGLE_FAN:
                break;

            }
            glProgramParameteriEXT(mGLHandle,GL_GEOMETRY_OUTPUT_TYPE_EXT,
                                   getGLGeometryOutputPrimitiveType(outputOperationType));

            glProgramParameteriEXT(mGLHandle,GL_GEOMETRY_VERTICES_OUT_EXT,
                                   mGeometryProgram->getGLSLProgram()->getMaxOutputVertices());
        }

        glLinkProgramARB( mGLHandle );
        glGetObjectParameterivARB( mGLHandle, GL_OBJECT_LINK_STATUS_ARB, &mLinked );
        // force logging and raise exception if not linked
        checkForGLSLError( "GLSLLinkProgram::Activate",
                           "Error linking GLSL Program Object : ", mGLHandle, !mLinked, !mLinked );
        if(mLinked)
        {
            logObjectInfo( String("GLSL link result : "), mGLHandle );
            buildGLUniformReferences();
            extractAttributes();
        }

    }

    if (mLinked)
    {
        checkForGLSLError( "GLSLLinkProgram::Activate",
                           "Error prior to using GLSL Program Object : ", mGLHandle, false, false);

        glUseProgramObjectARB( mGLHandle );

        checkForGLSLError( "GLSLLinkProgram::Activate",
                           "Error using GLSL Program Object : ", mGLHandle, false, false);
    }
}
Пример #7
0
	void GLSLGpuProgram::initialize()
	{

#if BS_OPENGL_4_5
		static const char* VERSION_CHARS = "450";
#elif BS_OPENGL_4_4
		static const char* VERSION_CHARS = "440";
#elif BS_OPENGL_4_3
		static const char* VERSION_CHARS = "430";
#elif BS_OPENGL_4_2
		static const char* VERSION_CHARS = "420";
#else
		static const char* VERSION_CHARS = "410";
#endif
		
		if (!isSupported())
		{
			mIsCompiled = false;
			mCompileMessages = "Specified GPU program type is not supported by the current render system.";

			GpuProgram::initialize();
			return;
		}

		GLenum shaderType = 0x0000;
		switch (mType)
		{
		case GPT_VERTEX_PROGRAM:
			shaderType = GL_VERTEX_SHADER;
			mProgramID = ++sVertexShaderCount;
			break;
		case GPT_FRAGMENT_PROGRAM:
			shaderType = GL_FRAGMENT_SHADER;
			mProgramID = ++sFragmentShaderCount;
			break;
#if BS_OPENGL_4_1 || BS_OPENGLES_3_2
		case GPT_GEOMETRY_PROGRAM:
			shaderType = GL_GEOMETRY_SHADER;
			mProgramID = ++sGeometryShaderCount;
			break;
		case GPT_HULL_PROGRAM:
			shaderType = GL_TESS_CONTROL_SHADER;
			mProgramID = ++sDomainShaderCount;
			break;
		case GPT_DOMAIN_PROGRAM:
			shaderType = GL_TESS_EVALUATION_SHADER;
			mProgramID = ++sHullShaderCount;
			break;
#endif
#if BS_OPENGL_4_3 || BS_OPENGLES_3_1
		case GPT_COMPUTE_PROGRAM:
			shaderType = GL_COMPUTE_SHADER;
			mProgramID = ++sComputeShaderCount;
			break;
#endif
		default:
			break;
		}

		// Add preprocessor extras and main source
		const String& source = mSource;
		if (!source.empty())
		{
			Vector<GLchar*> lines;

			const char* versionStr = "#version ";
			UINT32 versionStrLen = (UINT32)strlen(versionStr);

			UINT32 lineLength = 0;
			INT32 versionLineNum = -1;
			for (UINT32 i = 0; i < source.size(); i++)
			{
				if (source[i] == '\n' || source[i] == '\r')
				{
					assert(sizeof(source[i]) == sizeof(GLchar));

					GLchar* lineData = (GLchar*)bs_stack_alloc(sizeof(GLchar) * (lineLength + 2));
					memcpy(lineData, &source[i - lineLength], sizeof(GLchar) * lineLength);

					lineData[lineLength] = '\n';
					lineData[lineLength + 1] = '\0';

					if(versionLineNum == -1 && lineLength >= versionStrLen)
					{
						bool isEqual = true;
						for (UINT32 j = 0; j < versionStrLen; ++j)
						{
							if(lineData[j] != versionStr[j])
							{
								isEqual = false;
								break;
							}
						}

						if (isEqual)
							versionLineNum = (INT32)lines.size();
					}

					lines.push_back(lineData);
					lineLength = 0;
				}
				else
				{
					lineLength++;
				}
			}

			if (lineLength > 0)
			{
				UINT32 end = (UINT32)source.size() - 1;
				assert(sizeof(source[end]) == sizeof(GLchar));

				GLchar* lineData = (GLchar*)bs_stack_alloc(sizeof(GLchar) * (lineLength + 1));
				memcpy(lineData, &source[source.size() - lineLength], sizeof(GLchar) * lineLength);
				lineData[lineLength] = '\0';

				lines.push_back(lineData);
				lineLength = 0;
			}

			int numInsertedLines = 0;
			if(versionLineNum == -1)
			{
				char versionLine[50];
				strcpy(versionLine, "#version ");
				strcat(versionLine, VERSION_CHARS);
				strcat(versionLine, "\n");

				UINT32 length = (UINT32)strlen(versionLine) + 1;

				GLchar* extraLineData = (GLchar*)bs_stack_alloc(length);
				memcpy(extraLineData, versionLine, length);

				lines.insert(lines.begin(), extraLineData);
				numInsertedLines++;
			}

			char versionDefine[50];
			strcpy(versionDefine, "#define OPENGL");
			strcat(versionDefine, VERSION_CHARS);
			strcat(versionDefine, "\n");

			const char* EXTRA_LINES[] =
				{ 
					"#define OPENGL\n",
					versionDefine
				};

			UINT32 numExtraLines = sizeof(EXTRA_LINES) / sizeof(EXTRA_LINES[0]);
			UINT32 extraLineOffset = versionLineNum != -1 ? versionLineNum + 1 : 0;
			for (UINT32 i = 0; i < numExtraLines; i++)
			{
				UINT32 length = (UINT32)strlen(EXTRA_LINES[i]) + 1;

				GLchar* extraLineData = (GLchar*)bs_stack_alloc(length);
				memcpy(extraLineData, EXTRA_LINES[i], length);

				lines.insert(lines.begin() + extraLineOffset + numInsertedLines, extraLineData);
				numInsertedLines++;
			}

			StringStream codeStream;
			for(auto& entry : lines)
				codeStream << entry;

			for (INT32 i = numInsertedLines - 1; i >= 0; i--)
				bs_stack_free(lines[extraLineOffset + i]);

			if (numInsertedLines > 0)
				lines.erase(lines.begin() + extraLineOffset, lines.begin() + extraLineOffset + numInsertedLines);

			for (auto iter = lines.rbegin(); iter != lines.rend(); ++iter)
				bs_stack_free(*iter);

			String code = codeStream.str();
			const char* codeRaw = code.c_str();
			mGLHandle = glCreateShaderProgramv(shaderType, 1, (const GLchar**)&codeRaw);
			BS_CHECK_GL_ERROR();

			mCompileMessages = "";
			mIsCompiled = !checkForGLSLError(mGLHandle, mCompileMessages);
		}

		if (mIsCompiled)
		{
			GLSLParamParser paramParser;
			paramParser.buildUniformDescriptions(mGLHandle, mType, *mParametersDesc);

			if (mType == GPT_VERTEX_PROGRAM)
			{
				Vector<VertexElement> elementList = paramParser.buildVertexDeclaration(mGLHandle);
				mInputDeclaration = HardwareBufferManager::instance().createVertexDeclaration(elementList);
			}
		}

		BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_GpuProgram);
		GpuProgram::initialize();
	}