//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- void GLRenderToVertexBuffer::update(SceneManager* sceneMgr) { checkGLError(true, false, "start of GLRenderToVertexBuffer::update"); 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); checkGLError(true, false); 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); } GLHardwareVertexBuffer* vertexBuffer = static_cast<GLHardwareVertexBuffer*>(mVertexBuffers[targetBufferIndex].getPointer()); GLuint bufferId = vertexBuffer->getGLBufferId(); //Bind the target buffer glBindBufferOffsetNV(GL_TRANSFORM_FEEDBACK_BUFFER_NV, 0, bufferId, 0); glBeginTransformFeedbackNV(getR2VBPrimitiveType(mOperationType)); glEnable(GL_RASTERIZER_DISCARD_NV); // disable rasterization glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV, mPrimitivesDrawnQuery); 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->hasGeometryProgram()) { targetRenderSystem->bindGpuProgramParameters(GPT_GEOMETRY_PROGRAM, r2vbPass->getGeometryProgramParameters(), GPV_ALL); } targetRenderSystem->_render(renderOp); //Finish the query glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_NV); glDisable(GL_RASTERIZER_DISCARD_NV); glEndTransformFeedbackNV(); //read back query results GLuint primitivesWritten; glGetQueryObjectuiv(mPrimitivesDrawnQuery, GL_QUERY_RESULT, &primitivesWritten); mVertexData->vertexCount = primitivesWritten * getVertexCountPerPrimitive(mOperationType); checkGLError(true, true, "GLRenderToVertexBuffer::update"); //Switch the vertex binding if neccesary if (targetBufferIndex != mFrontBufferIndex) { mVertexData->vertexBufferBinding->unsetAllBindings(); mVertexData->vertexBufferBinding->setBinding(0, mVertexBuffers[targetBufferIndex]); mFrontBufferIndex = targetBufferIndex; } glDisable(GL_RASTERIZER_DISCARD_NV); // enable rasterization //Clear the reset flag mResetRequested = false; }
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; // } // 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 - mSourceBufferIndex; // } // if (mVertexBuffers[targetBufferIndex].isNull() || // mVertexBuffers[targetBufferIndex]->getSizeInBytes() != bufSize) // { // reallocateBuffer(targetBufferIndex); // } // 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); if (mFirstUpdate) { bindVerticesOutput(r2vbPass); mFirstUpdate = false; } // size_t targetBufferIndex = mSourceBufferIndex == 0 ? 0 : 1; // Disable rasterization. OGRE_CHECK_GL_ERROR(glEnable(GL_RASTERIZER_DISCARD)); // Bind shader parameters. RenderSystem* targetRenderSystem = Root::getSingleton().getRenderSystem(); 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); } //TODO add tessellation stages // Bind source vertex array + target tranform feedback buffer. GL3PlusHardwareVertexBuffer* targetVertexBuffer = static_cast<GL3PlusHardwareVertexBuffer*>(mVertexBuffers[mTargetBufferIndex].getPointer()); // OGRE_CHECK_GL_ERROR(glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, VertexBuffer[mTargetBufferIndex])); OGRE_CHECK_GL_ERROR(glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, targetVertexBuffer->getGLBufferId())); // OGRE_CHECK_GL_ERROR(glBindVertexArray(VertexArray[mSourceBufferIndex])); if (Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_SEPARATE_SHADER_OBJECTS)) { GLSLSeparableProgram* separableProgram = GLSLSeparableProgramManager::getSingleton().getCurrentSeparableProgram(); separableProgram->activate(); separableProgram->getVertexArrayObject()->bind(); } else { GLSLMonolithicProgram* monolithicProgram = GLSLMonolithicProgramManager::getSingleton().getActiveMonolithicProgram(); monolithicProgram->getVertexArrayObject()->bind(); } // 'Render' data to the transform buffer. OGRE_CHECK_GL_ERROR(glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, mPrimitivesDrawnQuery)); OGRE_CHECK_GL_ERROR(glBeginTransformFeedback(getR2VBPrimitiveType(mOperationType))); RenderOperation renderOp; if (mResetRequested || mResetsEveryUpdate) { // Use source data to render to first buffer. mSourceRenderable->getRenderOperation(renderOp); } else { // Use current front buffer to render to back buffer. this->getRenderOperation(renderOp); } renderOp.renderToVertexBuffer = true; targetRenderSystem->_render(renderOp); // OGRE_CHECK_GL_ERROR(glDrawArrays(GL_POINTS, 0, 1)); //TODO GL4+ //glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, mFeedbackObject); //glDrawTransformFeedback(getR2VBPrimitiveType(mOperationType), mFeedbackObject); OGRE_CHECK_GL_ERROR(glEndTransformFeedback()); OGRE_CHECK_GL_ERROR(glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN)); // 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. mVertexData->vertexBufferBinding->unsetAllBindings(); mVertexData->vertexBufferBinding->setBinding(0, mVertexBuffers[mTargetBufferIndex]); mTargetBufferIndex = mTargetBufferIndex == 0 ? 1 : 0; // Enable rasterization. OGRE_CHECK_GL_ERROR(glDisable(GL_RASTERIZER_DISCARD)); // Clear the reset flag. mResetRequested = false; }
void D3D11RenderToVertexBuffer::update(SceneManager* sceneMgr) { //Single pass only for now Ogre::Pass* r2vbPass = mMaterial->getBestTechnique()->getPass(0); setupGeometryShaderLinkageToStreamOut(r2vbPass); 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; } //Set pass before binding buffers to activate the GPU programs sceneMgr->_setPass(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 renderOp.operationType = mOperationType; renderOp.useIndexes = false; renderOp.vertexData = mVertexData; targetBufferIndex = 1 - mFrontBufferIndex; } if (mVertexBuffers[targetBufferIndex].isNull() || mVertexBuffers[targetBufferIndex]->getSizeInBytes() != bufSize) { reallocateBuffer(targetBufferIndex); } RenderSystem* targetRenderSystem = Root::getSingleton().getRenderSystem(); //Draw the object targetRenderSystem->_setWorldMatrix(Matrix4::IDENTITY); targetRenderSystem->_setViewMatrix(Matrix4::IDENTITY); targetRenderSystem->_setProjectionMatrix(Matrix4::IDENTITY); D3D11HardwareVertexBuffer* vertexBuffer = static_cast<D3D11HardwareVertexBuffer*>(mVertexBuffers[targetBufferIndex].getPointer()); UINT offset[1] = { 0 }; ID3D11Buffer* iBuffer[1]; iBuffer[0] = vertexBuffer->getD3DVertexBuffer(); mDevice.GetImmediateContext()->SOSetTargets( 1, iBuffer, offset ); if (r2vbPass->hasVertexProgram()) { targetRenderSystem->bindGpuProgramParameters(GPT_VERTEX_PROGRAM, r2vbPass->getVertexProgramParameters(), GPV_ALL); } if (r2vbPass->hasGeometryProgram()) { targetRenderSystem->bindGpuProgramParameters(GPT_GEOMETRY_PROGRAM, r2vbPass->getGeometryProgramParameters(), GPV_ALL); } mDevice.GetImmediateContext()->Begin(mDeviceStatsQuery); targetRenderSystem->_render(renderOp); //Switch the vertex binding if necessary if (targetBufferIndex != mFrontBufferIndex) { mVertexData->vertexBufferBinding->unsetAllBindings(); mVertexData->vertexBufferBinding->setBinding(0, mVertexBuffers[targetBufferIndex]); mFrontBufferIndex = targetBufferIndex; } ID3D11Buffer* nullBuffer[1]; nullBuffer[0]=NULL; mDevice.GetImmediateContext()->SOSetTargets( 1, nullBuffer, offset ); //Clear the reset flag mResetRequested = false; mDevice.GetImmediateContext()->End(mDeviceStatsQuery); D3D11_QUERY_DATA_PIPELINE_STATISTICS stats; while( S_OK != mDevice.GetImmediateContext()->GetData(mDeviceStatsQuery, &stats, mDeviceStatsQuery->GetDataSize(), 0 ) ){} }
//----------------------------------------------------------------------------- void GLES2RenderToVertexBuffer::update(SceneManager* sceneMgr) { size_t bufSize = mVertexData->vertexDeclaration->getVertexSize(0) * mMaxVertexCount; if (!mVertexBuffers[0] || 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] || mVertexBuffers[targetBufferIndex]->getSizeInBytes() != bufSize) { reallocateBuffer(targetBufferIndex); } GLES2HardwareVertexBuffer* vertexBuffer = static_cast<GLES2HardwareVertexBuffer*>(mVertexBuffers[targetBufferIndex].get()); /* if(Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_SEPARATE_SHADER_OBJECTS)) { GLSLESProgramPipeline* programPipeline = GLSLESProgramPipelineManager::getSingleton().getActiveProgramPipeline(); programPipeline->getVertexArrayObject()->bind(); } else { GLSLESLinkProgram* linkProgram = GLSLESLinkProgramManager::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; }