RenderResultPacket RenderServerRenderer::createRenderResultPacket(const RenderServerRenderRequest & request) { QByteArray outputBuffer; int bufferSizeBytes = m_renderer.getScreenBufferSizeBytes(); outputBuffer.resize(bufferSizeBytes); m_renderer.getOutputBuffer(outputBuffer.data()); RenderResultPacket result = RenderResultPacket(request.getSequenceNumber(), request.getIterationNumbers(), outputBuffer); return result; }
void RenderServerRenderer::pushCommandToQueue( RenderServerRenderRequest renderRequest ) { m_queueMutex.lock(); if(renderRequest.getSequenceNumber() > m_currentSequenceNumber) { m_currentSequenceNumber = renderRequest.getSequenceNumber(); m_renderTime.restart(); m_totalTime.restart(); } m_queue.enqueue(renderRequest); m_queueMutex.unlock(); m_waitCondition.wakeAll(); }
void StandaloneRenderManager::renderNextIteration() { try { if(m_application.getRunningStatus() == RunningStatus::RUNNING && m_currentScene != NULL) { m_noEmittedSignals = true; if(m_compileScene) { m_application.setRendererStatus(RendererStatus::INITIALIZING_SCENE); m_renderer.initScene(*m_currentScene); m_compileScene = false; m_application.setRendererStatus(RendererStatus::RENDERING); } // We only diplay one every X frames on screen (to make fair comparison with distributed renderer) bool shouldOutputIteration = m_nextIterationNumber % 5 == 0; const double PPMAlpha = 2.0/3.0; QVector<unsigned long long> iterationNumbers; QVector<double> ppmRadii; RenderServerRenderRequestDetails details (m_camera, QByteArray(m_currentScene->getSceneName()), m_application.getRenderMethod(), m_application.getWidth(), m_application.getHeight(), PPMAlpha); RenderServerRenderRequest renderRequest (m_application.getSequenceNumber(), iterationNumbers, ppmRadii, details); m_renderer.renderNextIteration(m_nextIterationNumber, m_nextIterationNumber, m_PPMRadius, shouldOutputIteration, renderRequest.getDetails()); const double ppmRadiusSquared = m_PPMRadius*m_PPMRadius; const double ppmRadiusSquaredNew = ppmRadiusSquared*(m_nextIterationNumber+PPMAlpha)/double(m_nextIterationNumber+1); m_PPMRadius = sqrt(ppmRadiusSquaredNew); // Transfer the output buffer to CPU and signal ready for display if(shouldOutputIteration) { if(m_outputBuffer == NULL) { m_outputBuffer = new float[2000*2000*3]; } m_renderer.getOutputBuffer(m_outputBuffer); emit newFrameReadyForDisplay(m_outputBuffer, m_nextIterationNumber); } fillRenderStatistics(); m_nextIterationNumber++; } } catch(const std::exception & E) { m_application.setRunningStatus(RunningStatus::PAUSE); QString error = QString("%1").arg(E.what()); emit renderManagerError(error); } }
void RenderServerRenderer::onNewRenderCommandInQueue() { while(true) { // Process queued up events/slots, in case we quit QCoreApplication::processEvents(); if(m_quit) { return; } // If queue is empty, we wait until we get a new request if(m_queue.size() == 0) { m_waitCondition.wait(&m_waitConditionMutex); continue; } // Process the next RenderServerRenderRequest RenderServerRenderRequest renderRequest = m_queue.dequeue(); QString iterationNumbersInPacketString = ""; for(int i = 0; i < renderRequest.getNumIterations(); i++) { // If the packet we are working has become old during this rendering for-loop, then break out of this loop if(m_currentSequenceNumber != renderRequest.getSequenceNumber()) { break; } // Else we'll render this frame else { // This renderRequest has a new scene name, so we'll load the new scene if(m_scene == NULL || m_scene->getSceneName() != renderRequest.getDetails().getSceneName()) { loadNewScene(renderRequest.getDetails().getSceneName()); } // Render the frame with local iteration number going from 0 to renderRequestsCurrentPacket.size() // We only need to create the output buffer for the last iteration of the packet bool createOutputBuffer = i == renderRequest.getNumIterations() - 1; renderFrame(renderRequest.getIterationNumbers().at(i), i, renderRequest.getPPMRadii().at(i), createOutputBuffer, renderRequest.getDetails()); iterationNumbersInPacketString += " " + QString::number(renderRequest.getIterationNumbers().at(i)); } } // If the packet we have just rendered is old (m_currentSequenceNumber is newer) // then we drop this packet. This can happen if we have started on a RenderServerRenderRequest but later found out about // a new sequence, in which case we have break-ed out of the loop above. if(renderRequest.getSequenceNumber() == m_currentSequenceNumber) { RenderResultPacket result = createRenderResultPacket(renderRequest); QString logString = QString("TRANSFERRING packet (%1 iteration:%2) in sequence %3 to client.") .arg(result.getNumIterationsInPacket()) .arg(iterationNumbersInPacketString) .arg(result.getSequenceNumber()); emit newLogString(logString); emit newRenderResultPacket(result); } else { QString logString = QString("IGNORED package with %1 iterations since sequence %3 != %4.") .arg(renderRequest.getNumIterations()) .arg(renderRequest.getSequenceNumber()) .arg(m_currentSequenceNumber); emit newLogString(logString); } } }
void StandaloneRenderManager::renderNextIteration() { try { if(m_application.getRunningStatus() == RunningStatus::RUNNING && m_currentScene != NULL) { m_noEmittedSignals = true; if(m_compileScene) { m_application.setRendererStatus(RendererStatus::INITIALIZING_SCENE); m_renderer.initScene(*m_currentScene); m_compileScene = false; m_application.setRendererStatus(RendererStatus::STARTING_RENDERING); } // We only display one every X frames on screen (to make fair comparison with distributed renderer) bool shouldOutputIteration = m_nextIterationNumber % 5 == 0; //bool shouldOutputIteration = m_nextIterationNumber % 1 == 0; const double PPMAlpha = 2.0/3.0; QVector<unsigned long long> iterationNumbers; QVector<double> ppmRadii; RenderServerRenderRequestDetails details (m_camera, QByteArray(m_currentScene->getSceneName()), m_application.getRenderMethod(), m_application.getWidth(), m_application.getHeight(), PPMAlpha); RenderServerRenderRequest renderRequest (m_application.getSequenceNumber(), iterationNumbers, ppmRadii, details); m_renderer.renderNextIteration(m_nextIterationNumber, m_nextIterationNumber, m_PPMRadius, shouldOutputIteration, renderRequest.getDetails()); const double ppmRadiusSquared = m_PPMRadius*m_PPMRadius; const double ppmRadiusSquaredNew = ppmRadiusSquared*(m_nextIterationNumber+PPMAlpha)/double(m_nextIterationNumber+1); m_PPMRadius = sqrt(ppmRadiusSquaredNew); // set as rendering only after first iteration, since that one can slow due init and sync with gpu if (m_application.getRendererStatus() != RendererStatus::RENDERING) m_application.setRendererStatus(RendererStatus::RENDERING); // Transfer the output buffer to CPU and signal ready for display m_outputBufferMutex.lock(); m_lastRendererIterationNumber = m_nextIterationNumber; if(shouldOutputIteration) { if(m_outputBuffer == NULL) { m_outputBuffer = new float[MAX_OUTPUT_X*MAX_OUTPUT_Y*3]; } m_renderer.getOutputBuffer(m_outputBuffer); // FIXME // vmarz: m_lastRendererIterationNumber shouldn't be exposed like that, but passed next iteration number // can be invalid (already incremented) when render widget is updating and accumulated values get scaled incorrectly emit newFrameReadyForDisplay(m_outputBuffer, &m_lastRendererIterationNumber, &m_outputBufferMutex); } m_outputBufferMutex.unlock(); fillRenderStatistics(); m_nextIterationNumber++; } } catch(const std::exception & E) { m_application.setRunningStatus(RunningStatus::PAUSE); QString error = QString("%1").arg(E.what()); emit renderManagerError(error); } }