Esempio n. 1
0
void ExternalInputSource::insertChar(Char ch)
{
  if (start() > buf_) {
    if (cur() > start())
      memmove((Char *)start() - 1, start(), (cur() - start())*sizeof(Char));
    moveLeft();
    *(Char *)cur() = ch;
  }
  else {
    // must have start == buf
    if (buf_ + (bufSize_ - (nLeftOver_ + sizeof(Char) - 1)/sizeof(Char))
	== bufLim_) {
      if (bufSize_ == size_t(-1))
	abort();		// FIXME throw an exception
      reallocateBuffer(bufSize_ + 1);
    }
    else if (nLeftOver_ > 0 && ((char *)(bufLim_ + 1) > leftOver_)) {
      char *s = (char *)(buf_ + bufSize_) - nLeftOver_;
      memmove(s, leftOver_, nLeftOver_);
      leftOver_ = s;
    }
    if (cur() < bufLim_)
      memmove((Char *)cur() + 1, cur(), (bufLim_ - cur())*sizeof(Char));
    *(Char *)cur() = ch;
    advanceEnd(end() + 1);
    bufLim_ += 1;
  }
}
Esempio n. 2
0
void ChainResampler::adjustRate(const long inRate, const long outRate) {
	unsigned long mul, div;
	
	exactRatio(mul, div);
	
	bigSinc->adjustDiv(static_cast<int>(static_cast<double>(inRate) * mul / (static_cast<double>(div / bigSinc->div()) * outRate) + 0.5));
	
	reallocateBuffer();
	setRate(inRate, outRate);
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
	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;
	}
Esempio n. 4
0
Xchar ExternalInputSource::fill(Messenger &mgr)
{
  ASSERT(cur() == end());
  while (end() >= bufLim_) {
    // need more data
    while (so_ == 0) {
      if (soIndex_ >= sov_.size())
	return eE;
      if (soIndex_ > 0)
	info_->noteStorageObjectEnd(bufLimOffset_ - (bufLim_ - end()));
      const StorageObjectSpec &spec = info_->spec(soIndex_);
      if (mayNotExist_) {
	NullMessenger nullMgr;
	sov_[soIndex_]
	  = spec.storageManager->makeStorageObject(spec.specId, spec.baseId,
						   spec.search,
						   mayRewind_, nullMgr,
						   info_->id(soIndex_));
      }
      else
	sov_[soIndex_]
	  = spec.storageManager->makeStorageObject(spec.specId, spec.baseId,
						   spec.search,
						   mayRewind_, mgr,
						   info_->id(soIndex_));
      so_ = sov_[soIndex_].pointer();
      if (so_) {
	decoder_ = spec.codingSystem->makeDecoder();
	info_->setDecoder(soIndex_, decoder_);
	zapEof_ = spec.zapEof;
	switch (spec.records) {
	case StorageObjectSpec::asis:
	  recordType_ = asis;
	  insertRS_ = false;
	  break;
	case StorageObjectSpec::cr:
	  recordType_ = cr;
	  break;
	case StorageObjectSpec::lf:
	  recordType_ = lf;
	  break;
	case StorageObjectSpec::crlf:
	  recordType_ = crlf;
	  break;
	case StorageObjectSpec::find:
	  recordType_ = unknown;
	  break;
	default:
	  CANNOT_HAPPEN();
	}
	soIndex_++;
	readSize_ = so_->getBlockSize();
	nLeftOver_ = 0;
	break;
      }
      else
	setAccessError();
      soIndex_++;
    }

    size_t keepSize = end() - start();
    const size_t align = sizeof(int)/sizeof(Char);
    size_t readSizeChars = (readSize_ + (sizeof(Char) - 1))/sizeof(Char);
    readSizeChars = roundUp(readSizeChars, align);
    size_t neededSize;		// in Chars
    size_t startOffset;
    // compute neededSize and readSize
    unsigned minBytesPerChar = decoder_->minBytesPerChar();
    if (nLeftOver_ == 0 && minBytesPerChar >= sizeof(Char)) {
      // In this case we want to do decoding in place.
      // FIXME It might be a win on some systems (Irix?) to arrange that the
      // read buffer is on a page boundary.

      if (keepSize >= size_t(-1)/sizeof(Char) - (align - 1) - insertRS_)
	abort();			// FIXME throw an exception
      
      // Now size_t(-1)/sizeof(Char) - (align - 1) - insertRS_ - keepSize > 0
      if (readSizeChars
	  > size_t(-1)/sizeof(Char) - (align - 1) - insertRS_ - keepSize)
	abort();
      neededSize = roundUp(readSizeChars + keepSize + insertRS_, align);
      startOffset = ((neededSize > bufSize_ ? neededSize : bufSize_)
		     - readSizeChars - insertRS_ - keepSize);
    }
    else {
      // Needs to be room for everything before decoding.
      neededSize = (keepSize + insertRS_ + readSizeChars
		    + (nLeftOver_ + sizeof(Char) - 1)/sizeof(Char));
      // Also must be room for everything after decoding.
      size_t neededSize2
	= (keepSize + insertRS_
	   // all the converted characters
	   + (nLeftOver_ + readSize_)/minBytesPerChar
	   // enough Chars to contain left over bytes
	   + ((readSize_ % minBytesPerChar + sizeof(Char) - 1)
	      / sizeof(Char)));
      if (neededSize2 > neededSize)
	neededSize = neededSize2;
      neededSize = roundUp(neededSize, align);
      if (neededSize > size_t(-1)/sizeof(Char))
	abort();
      startOffset = 0;
    }
    if (bufSize_ < neededSize)
      reallocateBuffer(neededSize);
    Char *newStart = buf_ + startOffset;
    if (newStart != start() && keepSize > 0)
      memmove(newStart, start(), keepSize*sizeof(Char));
    char *bytesStart = (char *)(buf_ + bufSize_ - readSizeChars) - nLeftOver_;
    if (nLeftOver_ > 0 && leftOver_ != bytesStart)
      memmove(bytesStart, leftOver_, nLeftOver_);
    moveStart(newStart);
    bufLim_ = end();

    size_t nread;
    if (so_->read((char *)(buf_ + bufSize_ - readSizeChars), readSize_,
		  mgr, nread)) {
      if (nread > 0) {
	const char *bytesEnd = bytesStart + nLeftOver_ + nread;
	size_t nChars = decoder_->decode((Char *)end() + insertRS_,
					 bytesStart,
					 nLeftOver_ + nread
					 - (zapEof_ && bytesEnd[-1] == EOFCHAR),
					 &leftOver_);
	nLeftOver_ = bytesEnd - leftOver_;
	if (nChars > 0) {
	  if (insertRS_) {
	    noteRS();
	    *(Char *)end() = RS;
	    advanceEnd(end() + 1);
	    insertRS_ = false;
	    bufLim_ += 1;
	    bufLimOffset_ += 1;
	  }
	  bufLim_ += nChars;
	  bufLimOffset_ += nChars;
	  break;
	}
      }
    }
    else
      so_ = 0;
  }
  ASSERT(end() < bufLim_);
  if (insertRS_) {
    noteRS();
    insertChar(RS);
    insertRS_ = false;
    bufLimOffset_ += 1;
  }
  switch (recordType_) {
  case unknown:
    {
      const Char *e = findNextCrOrLf(end(), bufLim_);
      if (e) {
	if (*e == '\n') {
	  recordType_ = lf;
	  info_->noteInsertedRSs();
	  *(Char *)e = RE;
	  advanceEnd(e + 1);
	  insertRS_ = true;
	}
	else {
	  if (e + 1 < bufLim_) {
	    if (e[1] == '\n') {
	      recordType_ = crlf;
	      advanceEnd(e + 1);
	      if (e + 2 == bufLim_) {
		bufLim_--;
		bufLimOffset_--;
		insertRS_ = true;
	      }
	    }
	    else {
	      advanceEnd(e + 1);
	      recordType_ = cr;
	      info_->noteInsertedRSs();
	      insertRS_ = true;
	    }
	  }
	  else {
	    recordType_ = crUnknown;
	    advanceEnd(e + 1);
	  }
	}
      }
      else
	advanceEnd(bufLim_);
    }
    break;
  case crUnknown:
    {
      if (*cur() == '\n') {
	noteRS();
	advanceEnd(cur() + 1);
	recordType_ = crlf;
      }
      else {
	advanceEnd(cur() + 1);
	insertRS_ = true;
	recordType_ = cr;
	info_->noteInsertedRSs();
      }
    }
    break;
  case lf:
    {
      Char *e = (Char *)findNextLf(end(), bufLim_);
      if (e) {
	advanceEnd(e + 1);
	*e = RE;
	insertRS_ = true;
      }
      else
	advanceEnd(bufLim_);
    }
    break;
  case cr:
    {
      const Char *e = findNextCr(end(), bufLim_);
      if (e) {
	advanceEnd(e + 1);
	insertRS_ = true;
      }
      else
	advanceEnd(bufLim_);
    }
    break;
  case crlf:
    {
      const Char *e = end();
      for (;;) {
	e = findNextLf(e, bufLim_);
	if (!e) {
	  advanceEnd(bufLim_);
	  break;
	}
	// Need to delete final RS if not followed by anything.
	if (e + 1 == bufLim_) {
	  bufLim_--;
	  bufLimOffset_--;
	  advanceEnd(e);
	  insertRS_ = true;
	  break;
	}
	noteRSAt(e);
	e++;
      }
    }
    break;
  case asis:
    advanceEnd(bufLim_);
    break;
  default:
    CANNOT_HAPPEN();
  }

  return nextChar();
}
	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 ) ){}
	}
Esempio n. 6
0
    void GL3PlusRenderToVertexBuffer::bindVerticesOutput(Pass* pass)
    {
        VertexDeclaration* declaration = mVertexData->vertexDeclaration;
        size_t elemCount = declaration->getElementCount();

        if (elemCount == 0)
            return;

        // Get program object ID.
        GLuint programId = 0;
        if (Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_SEPARATE_SHADER_OBJECTS))
        {
            GLSLSeparableProgram* separableProgram =
                GLSLSeparableProgramManager::getSingleton().getCurrentSeparableProgram();
            GLSLShader* glslGpuProgram = 0;
            if ((glslGpuProgram = separableProgram->getGeometryShader()))
                programId = glslGpuProgram->getGLProgramHandle();
            //TODO include tessellation stages
            else // vertex program
                programId = separableProgram->getVertexShader()->getGLProgramHandle();
        }
        else
        {
            GLSLMonolithicProgram* monolithicProgram = GLSLMonolithicProgramManager::getSingleton().getActiveMonolithicProgram();
            programId = monolithicProgram->getGLProgramHandle();
        }

        // Store the output in a buffer.  The buffer has the same
        // structure as the shader output vertex data.
        // 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.
        size_t sourceBufferIndex = mTargetBufferIndex == 0 ? 1 : 0;

        // Bind and fill vertex arrays + buffers.
        reallocateBuffer(sourceBufferIndex);
        reallocateBuffer(mTargetBufferIndex);
        // GL3PlusHardwareVertexBuffer* sourceVertexBuffer = static_cast<GL3PlusHardwareVertexBuffer*>(mVertexBuffers[mSourceBufferIndex].getPointer());
        // GL3PlusHardwareVertexBuffer* targetVertexBuffer = static_cast<GL3PlusHardwareVertexBuffer*>(mVertexBuffers[mTargetBufferIndex].getPointer());

        //TODO GL4+ glBindTransformFeedback

        // Dynamically determine shader output variable names.
        std::vector<String> nameStrings;
        std::vector<const GLchar*> names;
        for (uint e = 0; e < elemCount; e++)
        {
            const VertexElement* element = declaration->getElement(e);
            String name = getSemanticVaryingName(element->getSemantic(), element->getIndex());
            nameStrings.push_back(name);
        }

        // Convert to const char * for GL
        for (uint e = 0; e < elemCount; e++)
        {
            names.push_back(nameStrings[e].c_str());
        }

        //TODO replace glTransformFeedbackVaryings with in-shader specification (GL 4.4)
        OGRE_CHECK_GL_ERROR(glTransformFeedbackVaryings(programId, elemCount, &names[0], GL_INTERLEAVED_ATTRIBS));

        if (Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_SEPARATE_SHADER_OBJECTS))
        {
            GLSLSeparableProgram* separableProgram =
                GLSLSeparableProgramManager::getSingleton().getCurrentSeparableProgram();
            separableProgram->activate();
        }
        else
        {
            OGRE_CHECK_GL_ERROR(glLinkProgram(programId));
        }

#if OGRE_DEBUG_MODE
        // Check if program linking was successful.
        GLint didLink = 0;
        OGRE_CHECK_GL_ERROR(glGetProgramiv(programId, GL_LINK_STATUS, &didLink));
        logObjectInfo(String("RVB GLSL link result : "), programId);
        if (glIsProgram(programId))
        {
            glValidateProgram(programId);
        }
        logObjectInfo(String("RVB GLSL validation result : "), programId);

        // Check if varyings were successfully set.
        GLchar Name[64];
        GLsizei Length(0);
        GLsizei Size(0);
        GLenum Type(0);
        // bool Validated = false;
        for (size_t i = 0; i < elemCount; i++)
        {
            OGRE_CHECK_GL_ERROR(glGetTransformFeedbackVarying(
                programId, i, 64, &Length, &Size, &Type, Name
            ));
            std::cout << "Varying " << i << ": " << Name <<" "<< Length <<" "<< Size <<" "<< Type << std::endl;
            // Validated = (Size == 1) && (Type == GL_FLOAT_VEC3);
            // std::cout << Validated << " " << GL_FLOAT_VEC3 << std::endl;
        }
#endif
    }
//-----------------------------------------------------------------------------
    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;
    }