Exemplo n.º 1
0
 const StlVectorSet<VarOpnd *> *getChangedVarsSet() { 
     if (changedVars.empty()) {
         return 0;
     } else {
         if (removedPhiRecently) {
             changedVarsSet.clear();
             changedVarsSet.insert(changedVars.begin(), changedVars.end());
             removedPhiRecently = false;
         }
         return &changedVarsSet;
     }
 };
Exemplo n.º 2
0
	void RenderingContext::DrawInParallel( StlVector<std::shared_ptr<RenderingContext>>& contexts, const StlVector<std::shared_ptr<IMesh>>& meshes, int meshCount, FuncPreRender funcPreRender )
	{
		if ( meshes.empty() )
		{
			return;
		}

		if ( contexts.empty() )
		{
			LOG_WARNING( "no contexts" );
			return;
		}

		// Validate the specified rendering contexts.
		for ( auto context : contexts )
		{
			if ( context == nullptr )
			{
				LOG_WARNING( "forbidden null context usage" );
				return;
			}
		}

		if ( meshes.size() < static_cast<size_t>( meshCount ) )
		{
			LOG_WARNING( "invalid mesh count" );
			return;
		}

		// If the number of meshes is less than 4, 
		// draw all meshes on the first context without parallel processing.
		if ( meshCount < Thread::HardwareConcurrency() )
		{
			auto context = contexts[0];
			for ( const auto& mesh : meshes )
			{
				context->Draw( mesh );
			}
			return;
		}


		RenderingDevice* pDevice = RenderingDevice::GetInstance();
		Assert( pDevice );

		size_t numContexts = contexts.size();

		// Note that the world matrix would be multiplied just before drawing a mesh
		// because the world matrix of a mesh is different each other.
		// So premultiply view-projection matrices only.
		Matrix4 viewProj = pDevice->GetViewMatrix() * pDevice->GetProjectionMatrix();

		// Thread objects.
		ThreadPool* threadPool = ThreadPool::GetInstance();
		Atomic<int> workIndex( 0 );

		for ( size_t c = 0; c < numContexts; ++c )
		{
			auto context = contexts[c];
			Assert( context );

			auto task = std::bind(
				[=, &workIndex]( std::shared_ptr<RenderingContext> context, Matrix4 viewProj, FuncPreRender funcPreRender )
				{
					SCOPE_PROFILE_BEGIN( "RenderTask" );

					ConstantBuffer& cbuffer = context->GetSharedConstantBuffer();

					// Until the last index...
					while ( workIndex.Value() < meshCount )
					{
						// Prefech the workIndex to avoid changing the value on other thread, and then increment the workIndex.
						int index = workIndex.FetchAndIncrement();

						// Check the index again to guarantee atomic.
						// FIXME: Is this necessary?
						if ( index >= meshCount )
						{
							return;
						}

						// Call the PreRender functor.
						funcPreRender( context, index );

						// Now compute the final WVP matrix of this mesh.
						Matrix4 wvp = cbuffer.GetMatrix4( ConstantBuffer::WorldMatrix ) * viewProj;
						cbuffer.SetMatrix4( ConstantBuffer::WVPMatrix, wvp );

						// Draw the mesh.
						context->Draw( meshes[index] );
					}

					SCOPE_PROFILE_END();
				},
				context,
				viewProj,
				funcPreRender );

			threadPool->Queue( task );
		}


		// Join all rendering threads.
		SCOPE_PROFILE_BEGIN( "JoinRendering" );
		threadPool->WaitForAllTasks();
		SCOPE_PROFILE_END();

			
		//// Resolve the UAV to display using the main context.
		//// We assume that rendering order is independent.
		//SCOPE_PROFILE_BEGIN( "ResolveUnorderedAccessView " );
		//contexts[0]->ResolveUnorderedAccessViews( contexts );
		//SCOPE_PROFILE_END();
	}