bool tdnMesh::CreateIndexes( unsigned int numIndexes, const DWORD *indexArray ) { HRESULT hr( S_OK ); this->numIndexes = numIndexes; // インデックス配列のサイズ計算 unsigned int indexesSize = sizeof( DWORD ) * numIndexes; // インデックスnew hr = tdnSystem::GetDevice()->CreateIndexBuffer( indexesSize, // インデックス配列のバイト数 0, // 使用方法 D3DUSAGE D3DFMT_INDEX32, // フォーマット D3DPOOL_MANAGED, // ? &indexBuffer, // インデックスバッファ <out> NULL ); // ? if ( FAILED( hr ) ) return false; // バッファにコピー DWORD* workIndex( nullptr ); hr = indexBuffer->Lock( 0, 0, ( void** ) &workIndex, 0 ); // バッファロック (バファのポインター取得) if ( FAILED( hr ) ) return false; memcpy_s( workIndex, indexesSize, indexArray, indexesSize ); // バッファにインデックス情報をコピー hr = indexBuffer->Unlock(); // バッファロックを解除 if ( FAILED( hr ) ) return false; return true; }
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(); }