Fix shared data access in raytracer, tidy up render loop
Render loop lost track of which blocks had been rendered due to a synchronization issue. Specifically, std::vector<bool> is special-cased as a bitfield and so is pretty much guaranteed not to be atomic unless synchronized externally. Also: - Clean up types of a few variables - Clean up openmp sharing type of variables (may result in better optimization) - Replace shared rendered block count with an openmp reduction (results in fewer locks) Fixes: lp:1608289 * https://bugs.launchpad.net/kicad/+bug/1608289
This commit is contained in:
parent
67230ac8e7
commit
82ed0fde32
|
@ -353,33 +353,38 @@ void C3D_RENDER_RAYTRACING::rt_render_tracing( GLubyte *ptrPBO ,
|
||||||
{
|
{
|
||||||
m_isPreview = false;
|
m_isPreview = false;
|
||||||
|
|
||||||
unsigned int nrBlocks = m_blockPositions.size(); // Cache the number of blocks
|
const size_t nrBlocks = m_blockPositions.size();
|
||||||
unsigned startTime = GetRunningMicroSecs(); // Get time that started render this block
|
const unsigned startTime = GetRunningMicroSecs();
|
||||||
bool breakLoop = false; // It will be used to break the loop
|
bool breakLoop = false;
|
||||||
|
int numBlocksRendered = 0;
|
||||||
|
|
||||||
#pragma omp parallel for schedule(dynamic)
|
#pragma omp parallel for schedule(dynamic) shared(breakLoop) \
|
||||||
for( signed int iBlock = 0; iBlock < (int)nrBlocks; iBlock++ )
|
firstprivate(ptrPBO, nrBlocks, startTime) reduction(+:numBlocksRendered) default(none)
|
||||||
|
for( size_t iBlock = 0; iBlock < nrBlocks; iBlock++ )
|
||||||
{
|
{
|
||||||
|
|
||||||
#pragma omp flush(breakLoop)
|
#pragma omp flush(breakLoop)
|
||||||
if( !breakLoop ) // That is used to break the other threads
|
if( !breakLoop )
|
||||||
{
|
{
|
||||||
// Check if this block was already processed
|
bool process_block;
|
||||||
if( !m_blockPositionsWasProcessed[iBlock] )
|
|
||||||
|
// std::vector<bool> stuffs eight bools to each byte, so access to
|
||||||
|
// them can never be natively atomic.
|
||||||
|
#pragma omp critical(checkProcessBlock)
|
||||||
{
|
{
|
||||||
|
process_block = !m_blockPositionsWasProcessed[iBlock];
|
||||||
m_blockPositionsWasProcessed[iBlock] = true;
|
m_blockPositionsWasProcessed[iBlock] = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Render this block
|
if( process_block )
|
||||||
|
{
|
||||||
rt_render_trace_block( ptrPBO, iBlock );
|
rt_render_trace_block( ptrPBO, iBlock );
|
||||||
|
numBlocksRendered++;
|
||||||
#pragma omp atomic
|
|
||||||
m_nrBlocksRenderProgress++;
|
|
||||||
|
|
||||||
|
|
||||||
// Check if it spend already some time render and request to exit
|
// Check if it spend already some time render and request to exit
|
||||||
// to display the progress
|
// to display the progress
|
||||||
#ifdef _OPENMP
|
#ifdef _OPENMP
|
||||||
// This makes possible that only one thread (id 0) can check the time
|
|
||||||
if( omp_get_thread_num() == 0 )
|
if( omp_get_thread_num() == 0 )
|
||||||
#endif
|
#endif
|
||||||
if( (GetRunningMicroSecs() - startTime) > 150000 )
|
if( (GetRunningMicroSecs() - startTime) > 150000 )
|
||||||
|
@ -391,6 +396,8 @@ void C3D_RENDER_RAYTRACING::rt_render_tracing( GLubyte *ptrPBO ,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_nrBlocksRenderProgress += numBlocksRendered;
|
||||||
|
|
||||||
if( aStatusTextReporter )
|
if( aStatusTextReporter )
|
||||||
aStatusTextReporter->Report( wxString::Format( _( "Rendering: %.0f %%" ),
|
aStatusTextReporter->Report( wxString::Format( _( "Rendering: %.0f %%" ),
|
||||||
(float)(m_nrBlocksRenderProgress * 100) /
|
(float)(m_nrBlocksRenderProgress * 100) /
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include <plugins/3dapi/c3dmodel.h>
|
#include <plugins/3dapi/c3dmodel.h>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
/// Vector of materials
|
/// Vector of materials
|
||||||
typedef std::vector< CBLINN_PHONG_MATERIAL > MODEL_MATERIALS;
|
typedef std::vector< CBLINN_PHONG_MATERIAL > MODEL_MATERIALS;
|
||||||
|
@ -110,7 +111,7 @@ private:
|
||||||
unsigned long int m_stats_start_rendering_time;
|
unsigned long int m_stats_start_rendering_time;
|
||||||
|
|
||||||
/// Save the number of blocks progress of the render
|
/// Save the number of blocks progress of the render
|
||||||
unsigned int m_nrBlocksRenderProgress;
|
size_t m_nrBlocksRenderProgress;
|
||||||
|
|
||||||
CPOSTSHADER_SSAO m_postshader_ssao;
|
CPOSTSHADER_SSAO m_postshader_ssao;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue