00001 /*************************************************************************** 00002 * Copyright (C) 1998-2009 by authors (see AUTHORS.txt ) * 00003 * * 00004 * This file is part of LuxRender. * 00005 * * 00006 * Lux Renderer is free software; you can redistribute it and/or modify * 00007 * it under the terms of the GNU General Public License as published by * 00008 * the Free Software Foundation; either version 3 of the License, or * 00009 * (at your option) any later version. * 00010 * * 00011 * Lux Renderer is distributed in the hope that it will be useful, * 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00014 * GNU General Public License for more details. * 00015 * * 00016 * You should have received a copy of the GNU General Public License * 00017 * along with this program. If not, see <http://www.gnu.org/licenses/>. * 00018 * * 00019 * This project is based on PBRT ; see http://www.pbrt.org * 00020 * Lux Renderer website : http://www.luxrender.net * 00021 ***************************************************************************/ 00022 00023 // contribution.cpp* 00024 #include "lux.h" 00025 #include "contribution.h" 00026 #include "film.h" 00027 00028 namespace lux 00029 { 00030 00031 void ContributionBuffer::Buffer::Splat(Film *film) 00032 { 00033 for (u_int i = 0; i < pos; ++i) 00034 film->AddSample(&contribs[i]); 00035 pos = 0; 00036 } 00037 00038 void ContributionBuffer::Splat(Film *film) 00039 { 00040 for (u_int i = 0; i < buffers.size(); ++i) { 00041 for (u_int j = 0; j < buffers[i].size(); ++j) 00042 buffers[i][j]->Splat(film); 00043 } 00044 film->AddSampleCount(sampleCount); 00045 sampleCount = 0.f; 00046 } 00047 00048 ContributionPool::ContributionPool() { 00049 total = 0; 00050 while (total < CONTRIB_BUF_KEEPALIVE) { 00051 // Add free buffers to both CFree and CSplat 00052 // so we can ping-pong between them. 00053 CFree.push_back(new ContributionBuffer()); 00054 CSplat.push_back(new ContributionBuffer()); 00055 ++total; 00056 } 00057 } 00058 00059 void ContributionPool::End(ContributionBuffer *c) 00060 { 00061 fast_mutex::scoped_lock poolAction(poolMutex); 00062 00063 if (c) 00064 CFull.push_back(c); 00065 00066 // Any splatting not done by other threads 00067 // will be done in Flush. 00068 } 00069 00070 ContributionBuffer* ContributionPool::Next(ContributionBuffer *c) 00071 { 00072 fast_mutex::scoped_lock poolAction(poolMutex); 00073 00074 if (c) 00075 CFull.push_back(c); 00076 00077 // If there are no free buffers, perform splat 00078 if (CFree.empty()) { 00079 // Since we're still holding the pool lock, 00080 // no other thread will perform the above test 00081 // until CFree is filled with free buffers again. 00082 // This prevents a thread from trying to splat 00083 // prematurely. 00084 boost::mutex::scoped_lock splattingAction(splattingMutex); 00085 00086 // CSplat contains available buffers 00087 // from last splatting. 00088 // CFull contains filled buffers ready for splatting. 00089 // CFree is empty. 00090 CSplat.swap(CFull); 00091 CFull.swap(CFree); 00092 // CSplat now contains filled buffers, 00093 // CFull is empty and 00094 // CFree contains available buffers. 00095 00096 // Dade - Bug 582 fix: allocate a new buffer if CFree is empty. 00097 ContributionBuffer *cold; 00098 if (CFree.empty()) 00099 cold = new ContributionBuffer(); 00100 else { 00101 // Store one free buffer for later, this way 00102 // we don't have to lock the pool lock again. 00103 cold = CFree.back(); 00104 CFree.pop_back(); 00105 } 00106 00107 // release the pool lock 00108 poolAction.unlock(); 00109 00110 for(u_int i = 0; i < CSplat.size(); ++i) 00111 CSplat[i]->Splat(film); 00112 00113 // return previously obtained buffer 00114 return cold; 00115 } 00116 00117 ContributionBuffer *cold = CFree.back(); 00118 CFree.pop_back(); 00119 00120 return cold; 00121 } 00122 00123 void ContributionPool::Flush() 00124 { 00125 for(u_int i = 0; i < CFull.size(); ++i) 00126 CSplat.push_back(CFull[i]); 00127 00128 CFull.clear(); 00129 00130 for(u_int i = 0; i < CSplat.size(); ++i) 00131 CSplat[i]->Splat(film); 00132 } 00133 00134 void ContributionPool::Delete() 00135 { 00136 for(u_int i = 0; i < CFree.size(); ++i) 00137 delete CFree[i]; 00138 for(u_int i = 0; i < CFull.size(); ++i) 00139 delete CFull[i]; 00140 for(u_int i = 0; i < CSplat.size(); ++i) 00141 delete CSplat[i]; 00142 } 00143 00144 void ContributionPool::CheckFilmWriteOuputInterval() 00145 { 00146 boost::mutex::scoped_lock splattingAction(splattingMutex); 00147 film->CheckWriteOuputInterval(); 00148 } 00149 00150 }