//----------------------------------------------------------------------------- void GLSLGpuProgram::bindProgramPassIterationParameters(GpuProgramParametersSharedPtr params) { // activate the link program object GLSLLinkProgram* linkProgram = GLSLLinkProgramManager::getSingleton().getActiveLinkProgram(); // pass on parameters from params to program object uniforms linkProgram->updatePassIterationUniforms( params ); }
//----------------------------------------------------------------------------- void GLSLGpuProgram::bindProgramParameters(GpuProgramParametersSharedPtr params, uint16 mask) { // link can throw exceptions, ignore them at this point try { // activate the link program object GLSLLinkProgram* linkProgram = GLSLLinkProgramManager::getSingleton().getActiveLinkProgram(); // pass on parameters from params to program object uniforms linkProgram->updateUniforms(params, mask, mType); } catch (Exception& e) {} }
//----------------------------------------------------------------------------- bool GLSLGpuProgram::isAttributeValid(VertexElementSemantic semantic, uint index) { // get link program - only call this in the context of bound program GLSLLinkProgram* linkProgram = GLSLLinkProgramManager::getSingleton().getActiveLinkProgram(); if (linkProgram->isAttributeValid(semantic, index)) { return true; } else { // fall back to default implementation, allow default bindings return GLGpuProgram::isAttributeValid(semantic, index); } }
//----------------------------------------------------------------------------- void GL3PlusRenderToVertexBuffer::bindVerticesOutput(Pass* pass) { VertexDeclaration* declaration = mVertexData->vertexDeclaration; size_t elemCount = declaration->getElementCount(); if (elemCount > 0) { GLuint linkProgramId = 0; // Have GLSL shaders, using varying attributes if(Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_SEPARATE_SHADER_OBJECTS)) { GLSLProgramPipeline* programPipeline = GLSLProgramPipelineManager::getSingleton().getActiveProgramPipeline(); linkProgramId = programPipeline->getGLProgramPipelineHandle(); } else { GLSLLinkProgram* linkProgram = GLSLLinkProgramManager::getSingleton().getActiveLinkProgram(); linkProgramId = linkProgram->getGLProgramHandle(); } // Note: 64 is the minimum number of interleaved attributes allowed by GL_EXT_transform_feedback // So we are using it. Otherwise we could query during rendersystem initialisation and use a dynamic sized array. // But that would require C99. // const GLchar *names[64]; const GLchar *names[1] = {"gl_Position"};//, "oUv0", "oUv1", "oUv2" }; // vector<const GLchar*>::type names; // for (unsigned short e = 0; e < elemCount; e++) // { // const VertexElement* element = declaration->getElement(e); // String varyingName = getSemanticVaryingName(element->getSemantic(), element->getIndex()); // names[e] = varyingName.c_str(); //// names.push_back(varyingName.c_str()); // } OGRE_CHECK_GL_ERROR(glTransformFeedbackVaryings(linkProgramId, elemCount, names, GL_INTERLEAVED_ATTRIBS)); OGRE_CHECK_GL_ERROR(glLinkProgram(linkProgramId)); GLint didLink = 0; OGRE_CHECK_GL_ERROR(glGetProgramiv( linkProgramId, GL_LINK_STATUS, &didLink )); logObjectInfo( String("RVB GLSL link result : "), linkProgramId ); if(glIsProgram(linkProgramId)) { glValidateProgram(linkProgramId); } logObjectInfo( String("RVB GLSL validation result : "), linkProgramId ); } }
//----------------------------------------------------------------------------- void GLSLGpuProgram::bindProgramPassIterationParameters(GpuProgramParametersSharedPtr params) { if(Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_SEPARATE_SHADER_OBJECTS)) { // Activate the program pipeline object GLSLProgramPipeline* programPipeline = GLSLProgramPipelineManager::getSingleton().getActiveProgramPipeline(); // Pass on parameters from params to program object uniforms programPipeline->updatePassIterationUniforms( params ); } else { // Activate the link program object GLSLLinkProgram* linkProgram = GLSLLinkProgramManager::getSingleton().getActiveLinkProgram(); // Pass on parameters from params to program object uniforms linkProgram->updatePassIterationUniforms( params ); } }
//----------------------------------------------------------------------------- void GLSLGpuProgram::bindProgramParameters(GpuProgramParametersSharedPtr params, uint16 mask) { // Link can throw exceptions, ignore them at this point try { if(Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_SEPARATE_SHADER_OBJECTS)) { // Activate the program pipeline object GLSLProgramPipeline* programPipeline = GLSLProgramPipelineManager::getSingleton().getActiveProgramPipeline(); // Pass on parameters from params to program object uniforms programPipeline->updateUniforms(params, mask, mType); } else { // Activate the link program object GLSLLinkProgram* linkProgram = GLSLLinkProgramManager::getSingleton().getActiveLinkProgram(); // Pass on parameters from params to program object uniforms linkProgram->updateUniforms(params, mask, mType); } } catch (Exception& e) {} }
//----------------------------------------------------------------------------- void GLRenderToVertexBuffer::bindVerticesOutput(Pass* pass) { VertexDeclaration* declaration = mVertexData->vertexDeclaration; bool useVaryingAttributes = false; //Check if we are FixedFunc/ASM shaders (Static attributes) or GLSL (Varying attributes) //We assume that there isn't a mix of GLSL and ASM as this is illegal GpuProgram* sampleProgram = 0; if (pass->hasVertexProgram()) { sampleProgram = pass->getVertexProgram().getPointer(); } else if (pass->hasGeometryProgram()) { sampleProgram = pass->getGeometryProgram().getPointer(); } if ((sampleProgram != 0) && (sampleProgram->getLanguage() == "glsl")) { useVaryingAttributes = true; } if (useVaryingAttributes) { //Have GLSL shaders, using varying attributes GLSLLinkProgram* linkProgram = GLSLLinkProgramManager::getSingleton().getActiveLinkProgram(); GLhandleARB linkProgramId = linkProgram->getGLHandle(); vector<GLint>::type locations; for (unsigned short e=0; e < declaration->getElementCount(); e++) { const VertexElement* element =declaration->getElement(e); String varyingName = getSemanticVaryingName(element->getSemantic(), element->getIndex()); GLint location = glGetVaryingLocationNV(linkProgramId, varyingName.c_str()); if (location < 0) { OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "GLSL link program does not output " + varyingName + " so it cannot fill the requested vertex buffer", "OgreGLRenderToVertexBuffer::bindVerticesOutput"); } locations.push_back(location); } glTransformFeedbackVaryingsNV( linkProgramId, static_cast<GLsizei>(locations.size()), &locations[0], GL_INTERLEAVED_ATTRIBS_NV); } else { //Either fixed function or assembly (CG = assembly) shaders vector<GLint>::type attribs; for (unsigned short e=0; e < declaration->getElementCount(); e++) { const VertexElement* element = declaration->getElement(e); //Type attribs.push_back(getGLSemanticType(element->getSemantic())); //Number of components attribs.push_back(VertexElement::getTypeCount(element->getType())); //Index attribs.push_back(element->getIndex()); } glTransformFeedbackAttribsNV( static_cast<GLuint>(declaration->getElementCount()), &attribs[0], GL_INTERLEAVED_ATTRIBS_NV); } checkGLError(true, true, "GLRenderToVertexBuffer::bindVerticesOutput"); }
//----------------------------------------------------------------------------- void GL3PlusRenderToVertexBuffer::update(SceneManager* sceneMgr) { size_t bufSize = mVertexData->vertexDeclaration->getVertexSize(0) * mMaxVertexCount; if (mVertexBuffers[0].isNull() || mVertexBuffers[0]->getSizeInBytes() != bufSize) { // Buffers don't match. Need to reallocate. mResetRequested = true; } // Single pass only for now Ogre::Pass* r2vbPass = mMaterial->getBestTechnique()->getPass(0); // Set pass before binding buffers to activate the GPU programs sceneMgr->_setPass(r2vbPass); bindVerticesOutput(r2vbPass); RenderOperation renderOp; size_t targetBufferIndex; if (mResetRequested || mResetsEveryUpdate) { // Use source data to render to first buffer mSourceRenderable->getRenderOperation(renderOp); targetBufferIndex = 0; } else { // Use current front buffer to render to back buffer this->getRenderOperation(renderOp); targetBufferIndex = 1 - mFrontBufferIndex; } if (mVertexBuffers[targetBufferIndex].isNull() || mVertexBuffers[targetBufferIndex]->getSizeInBytes() != bufSize) { reallocateBuffer(targetBufferIndex); } // Disable rasterization OGRE_CHECK_GL_ERROR(glEnable(GL_RASTERIZER_DISCARD)); GL3PlusHardwareVertexBuffer* vertexBuffer = static_cast<GL3PlusHardwareVertexBuffer*>(mVertexBuffers[targetBufferIndex].getPointer()); // Bind the target buffer OGRE_CHECK_GL_ERROR(glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, vertexBuffer->getGLBufferId())); if(Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_SEPARATE_SHADER_OBJECTS)) { GLSLProgramPipeline* programPipeline = GLSLProgramPipelineManager::getSingleton().getActiveProgramPipeline(); programPipeline->getVertexArrayObject()->bind(); } else { GLSLLinkProgram* linkProgram = GLSLLinkProgramManager::getSingleton().getActiveLinkProgram(); linkProgram->getVertexArrayObject()->bind(); } // Bind the target buffer OGRE_CHECK_GL_ERROR(glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, vertexBuffer->getGLBufferId())); // Disable rasterization OGRE_CHECK_GL_ERROR(glEnable(GL_RASTERIZER_DISCARD)); RenderSystem* targetRenderSystem = Root::getSingleton().getRenderSystem(); // Draw the object targetRenderSystem->_setWorldMatrix(Matrix4::IDENTITY); targetRenderSystem->_setViewMatrix(Matrix4::IDENTITY); targetRenderSystem->_setProjectionMatrix(Matrix4::IDENTITY); if (r2vbPass->hasVertexProgram()) { targetRenderSystem->bindGpuProgramParameters(GPT_VERTEX_PROGRAM, r2vbPass->getVertexProgramParameters(), GPV_ALL); } if (r2vbPass->hasFragmentProgram()) { targetRenderSystem->bindGpuProgramParameters(GPT_FRAGMENT_PROGRAM, r2vbPass->getFragmentProgramParameters(), GPV_ALL); } if (r2vbPass->hasGeometryProgram()) { targetRenderSystem->bindGpuProgramParameters(GPT_GEOMETRY_PROGRAM, r2vbPass->getGeometryProgramParameters(), GPV_ALL); } OGRE_CHECK_GL_ERROR(glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, mPrimitivesDrawnQuery)); OGRE_CHECK_GL_ERROR(glBeginTransformFeedback(getR2VBPrimitiveType(mOperationType))); targetRenderSystem->_render(renderOp); OGRE_CHECK_GL_ERROR(glEndTransformFeedback()); // Finish the query OGRE_CHECK_GL_ERROR(glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN)); OGRE_CHECK_GL_ERROR(glDisable(GL_RASTERIZER_DISCARD)); // Read back query results GLuint primitivesWritten; OGRE_CHECK_GL_ERROR(glGetQueryObjectuiv(mPrimitivesDrawnQuery, GL_QUERY_RESULT, &primitivesWritten)); mVertexData->vertexCount = primitivesWritten * getVertexCountPerPrimitive(mOperationType); // Switch the vertex binding if necessary if (targetBufferIndex != mFrontBufferIndex) { mVertexData->vertexBufferBinding->unsetAllBindings(); mVertexData->vertexBufferBinding->setBinding(0, mVertexBuffers[targetBufferIndex]); mFrontBufferIndex = targetBufferIndex; } // Enable rasterization OGRE_CHECK_GL_ERROR(glDisable(GL_RASTERIZER_DISCARD)); // Clear the reset flag mResetRequested = false; }