Automated merge with ssh://hg.lindenlab.com/davep/viewer-mesh/
commit
71422c6820
|
|
@ -6716,7 +6716,18 @@
|
|||
<key>Value</key>
|
||||
<integer>1</integer>
|
||||
</map>
|
||||
|
||||
<key>RenderPerformanceTest</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
<string>Disable rendering of everything but in-world content for
|
||||
performance testing</string>
|
||||
<key>Persist</key>
|
||||
<integer>1</integer>
|
||||
<key>Type</key>
|
||||
<string>Boolean</string>
|
||||
<key>Value</key>
|
||||
<integer>0</integer>
|
||||
</map>
|
||||
<key>RenderLightingDetail</key>
|
||||
<map>
|
||||
<key>Comment</key>
|
||||
|
|
|
|||
|
|
@ -1292,6 +1292,26 @@ bool LLAppViewer::cleanup()
|
|||
// workaround for DEV-35406 crash on shutdown
|
||||
LLEventPumps::instance().reset();
|
||||
|
||||
if (LLFastTimerView::sAnalyzePerformance)
|
||||
{
|
||||
llinfos << "Analyzing performance" << llendl;
|
||||
|
||||
if(LLFastTimer::sLog)
|
||||
{
|
||||
LLFastTimerView::doAnalysis(
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "performance_baseline.slp"),
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "performance.slp"),
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "performance_report.csv"));
|
||||
}
|
||||
if(LLFastTimer::sMetricLog)
|
||||
{
|
||||
LLFastTimerView::doAnalysis(
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "metric_baseline.slp"),
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "metric.slp"),
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "metric_report.csv"));
|
||||
}
|
||||
}
|
||||
|
||||
// remove any old breakpad minidump files from the log directory
|
||||
if (! isError())
|
||||
{
|
||||
|
|
@ -1630,25 +1650,6 @@ bool LLAppViewer::cleanup()
|
|||
delete mFastTimerLogThread;
|
||||
mFastTimerLogThread = NULL;
|
||||
|
||||
if (LLFastTimerView::sAnalyzePerformance)
|
||||
{
|
||||
llinfos << "Analyzing performance" << llendl;
|
||||
|
||||
if(LLFastTimer::sLog)
|
||||
{
|
||||
LLFastTimerView::doAnalysis(
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "performance_baseline.slp"),
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "performance.slp"),
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "performance_report.csv"));
|
||||
}
|
||||
if(LLFastTimer::sMetricLog)
|
||||
{
|
||||
LLFastTimerView::doAnalysis(
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "metric_baseline.slp"),
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "metric.slp"),
|
||||
gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "metric_report.csv"));
|
||||
}
|
||||
}
|
||||
LLMetricPerformanceTester::cleanClass() ;
|
||||
|
||||
llinfos << "Cleaning up Media and Textures" << llendflush;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,9 @@
|
|||
#include "llrect.h"
|
||||
#include "llerror.h"
|
||||
#include "llgl.h"
|
||||
#include "llimagepng.h"
|
||||
#include "llrender.h"
|
||||
#include "llrendertarget.h"
|
||||
#include "lllocalcliprect.h"
|
||||
#include "llmath.h"
|
||||
#include "llfontgl.h"
|
||||
|
|
@ -1016,6 +1018,370 @@ F64 LLFastTimerView::getTime(const std::string& name)
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
void saveChart(const std::string& label, const char* suffix, LLImageRaw* scratch)
|
||||
{
|
||||
//read result back into raw image
|
||||
glReadPixels(0, 0, 1024, 512, GL_RGB, GL_UNSIGNED_BYTE, scratch->getData());
|
||||
|
||||
//write results to disk
|
||||
LLPointer<LLImagePNG> result = new LLImagePNG();
|
||||
result->encode(scratch, 0.f);
|
||||
|
||||
std::string ext = result->getExtension();
|
||||
std::string filename = llformat("%s_%s.%s", label.c_str(), suffix, ext.c_str());
|
||||
|
||||
std::string out_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, filename);
|
||||
result->save(out_file);
|
||||
}
|
||||
|
||||
template <class VEC_TYPE>
|
||||
void removeOutliers(std::vector<VEC_TYPE>& data, F32 k)
|
||||
{
|
||||
if (data.size() < 100)
|
||||
{ //not enough samples
|
||||
return;
|
||||
}
|
||||
|
||||
VEC_TYPE Q1 = data[data.size()/4];
|
||||
VEC_TYPE Q3 = data[data.size()-data.size()/4-1];
|
||||
|
||||
VEC_TYPE min = Q1-k*(Q3-Q1);
|
||||
VEC_TYPE max = Q3+k*(Q3-Q1);
|
||||
|
||||
U32 i = 0;
|
||||
while (i < data.size() && data[i] < min)
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
S32 j = data.size()-1;
|
||||
while (j > 0 && data[j] > max)
|
||||
{
|
||||
j--;
|
||||
}
|
||||
|
||||
if (j < data.size()-1)
|
||||
{
|
||||
data.erase(data.begin()+j, data.end());
|
||||
}
|
||||
|
||||
if (i > 0)
|
||||
{
|
||||
data.erase(data.begin(), data.begin()+i);
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLFastTimerView::exportCharts(const std::string& base, const std::string& target)
|
||||
{
|
||||
//allocate render target for drawing charts
|
||||
LLRenderTarget buffer;
|
||||
buffer.allocate(1024,512, GL_RGB, FALSE, FALSE);
|
||||
|
||||
|
||||
LLSD cur;
|
||||
|
||||
LLSD base_data;
|
||||
|
||||
{ //read base log into memory
|
||||
S32 i = 0;
|
||||
std::ifstream is(base.c_str());
|
||||
while (!is.eof() && LLSDSerialize::fromXML(cur, is))
|
||||
{
|
||||
base_data[i++] = cur;
|
||||
}
|
||||
is.close();
|
||||
}
|
||||
|
||||
LLSD cur_data;
|
||||
std::set<std::string> chart_names;
|
||||
|
||||
{ //read current log into memory
|
||||
S32 i = 0;
|
||||
std::ifstream is(target.c_str());
|
||||
while (!is.eof() && LLSDSerialize::fromXML(cur, is))
|
||||
{
|
||||
cur_data[i++] = cur;
|
||||
|
||||
for (LLSD::map_iterator iter = cur.beginMap(); iter != cur.endMap(); ++iter)
|
||||
{
|
||||
std::string label = iter->first;
|
||||
chart_names.insert(label);
|
||||
}
|
||||
}
|
||||
is.close();
|
||||
}
|
||||
|
||||
//get time domain
|
||||
LLSD::Real cur_total_time = 0.0;
|
||||
|
||||
for (U32 i = 0; i < cur_data.size(); ++i)
|
||||
{
|
||||
cur_total_time += cur_data[i]["Total"]["Time"].asReal();
|
||||
}
|
||||
|
||||
LLSD::Real base_total_time = 0.0;
|
||||
for (U32 i = 0; i < base_data.size(); ++i)
|
||||
{
|
||||
base_total_time += base_data[i]["Total"]["Time"].asReal();
|
||||
}
|
||||
|
||||
LLSD::Real total_time = llmax(base_total_time, cur_total_time);
|
||||
|
||||
|
||||
//allocate raw scratch space
|
||||
LLPointer<LLImageRaw> scratch = new LLImageRaw(1024, 512, 3);
|
||||
|
||||
gGL.pushMatrix();
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(-0.05, 1.05, -0.05, 1.05, -1.0, 1.0);
|
||||
|
||||
//render charts
|
||||
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
|
||||
|
||||
buffer.bindTarget();
|
||||
|
||||
for (std::set<std::string>::iterator iter = chart_names.begin(); iter != chart_names.end(); ++iter)
|
||||
{
|
||||
std::string label = *iter;
|
||||
|
||||
LLSD::Real cur_start_time = -1.0;
|
||||
LLSD::Real cur_end_time = 0.0;
|
||||
|
||||
LLSD::Real max_time = 0.0;
|
||||
LLSD::Integer max_calls = 0.0;
|
||||
LLSD::Real max_execution = 0.0;
|
||||
|
||||
std::vector<LLSD::Real> cur_execution;
|
||||
std::vector<LLSD::Real> cur_times;
|
||||
std::vector<LLSD::Integer> cur_calls;
|
||||
|
||||
std::vector<LLSD::Real> base_execution;
|
||||
std::vector<LLSD::Real> base_times;
|
||||
std::vector<LLSD::Integer> base_calls;
|
||||
|
||||
for (U32 i = 0; i < cur_data.size(); ++i)
|
||||
{
|
||||
LLSD::Real time = cur_data[i][label]["Time"].asReal();
|
||||
LLSD::Integer calls = cur_data[i][label]["Calls"].asInteger();
|
||||
|
||||
LLSD::Real execution = 0.0;
|
||||
if (calls > 0)
|
||||
{
|
||||
execution = time/calls;
|
||||
cur_execution.push_back(execution);
|
||||
cur_times.push_back(time);
|
||||
}
|
||||
|
||||
cur_calls.push_back(calls);
|
||||
}
|
||||
|
||||
for (U32 i = 0; i < base_data.size(); ++i)
|
||||
{
|
||||
LLSD::Real time = base_data[i][label]["Time"].asReal();
|
||||
LLSD::Integer calls = base_data[i][label]["Calls"].asInteger();
|
||||
|
||||
LLSD::Real execution = 0.0;
|
||||
if (calls > 0)
|
||||
{
|
||||
execution = time/calls;
|
||||
base_execution.push_back(execution);
|
||||
base_times.push_back(time);
|
||||
}
|
||||
|
||||
base_calls.push_back(calls);
|
||||
}
|
||||
|
||||
std::sort(base_calls.begin(), base_calls.end());
|
||||
std::sort(base_times.begin(), base_times.end());
|
||||
std::sort(base_execution.begin(), base_execution.end());
|
||||
|
||||
std::sort(cur_calls.begin(), cur_calls.end());
|
||||
std::sort(cur_times.begin(), cur_times.end());
|
||||
std::sort(cur_execution.begin(), cur_execution.end());
|
||||
|
||||
//remove outliers
|
||||
const U32 OUTLIER_CUTOFF = 512;
|
||||
if (base_times.size() > OUTLIER_CUTOFF)
|
||||
{
|
||||
removeOutliers(base_times, 1.f);
|
||||
}
|
||||
|
||||
if (base_execution.size() > OUTLIER_CUTOFF)
|
||||
{
|
||||
removeOutliers(base_execution, 1.f);
|
||||
}
|
||||
|
||||
if (cur_times.size() > OUTLIER_CUTOFF)
|
||||
{
|
||||
removeOutliers(cur_times, 1.f);
|
||||
}
|
||||
|
||||
if (cur_execution.size() > OUTLIER_CUTOFF)
|
||||
{
|
||||
removeOutliers(cur_execution, 1.f);
|
||||
}
|
||||
|
||||
|
||||
max_time = llmax(base_times.empty() ? 0.0 : *base_times.rbegin(), cur_times.empty() ? 0.0 : *cur_times.rbegin());
|
||||
max_calls = llmax(base_calls.empty() ? 0 : *base_calls.rbegin(), cur_calls.empty() ? 0 : *cur_calls.rbegin());
|
||||
max_execution = llmax(base_execution.empty() ? 0.0 : *base_execution.rbegin(), cur_execution.empty() ? 0.0 : *cur_execution.rbegin());
|
||||
|
||||
|
||||
LLVector3 last_p;
|
||||
|
||||
//====================================
|
||||
// basic
|
||||
//====================================
|
||||
buffer.clear();
|
||||
|
||||
last_p.clear();
|
||||
|
||||
LLGLDisable cull(GL_CULL_FACE);
|
||||
|
||||
LLVector3 base_col(0, 0.7f, 0.f);
|
||||
LLVector3 cur_col(1.f, 0.f, 0.f);
|
||||
|
||||
gGL.setSceneBlendType(LLRender::BT_ADD);
|
||||
|
||||
gGL.color3fv(base_col.mV);
|
||||
for (U32 i = 0; i < base_times.size(); ++i)
|
||||
{
|
||||
gGL.begin(LLRender::TRIANGLE_STRIP);
|
||||
gGL.vertex3fv(last_p.mV);
|
||||
gGL.vertex3f(last_p.mV[0], 0.f, 0.f);
|
||||
last_p.set((F32)i/(F32) base_times.size(), base_times[i]/max_time, 0.f);
|
||||
gGL.vertex3fv(last_p.mV);
|
||||
gGL.vertex3f(last_p.mV[0], 0.f, 0.f);
|
||||
gGL.end();
|
||||
}
|
||||
|
||||
gGL.flush();
|
||||
|
||||
|
||||
last_p.clear();
|
||||
{
|
||||
LLGLEnable blend(GL_BLEND);
|
||||
|
||||
gGL.color3fv(cur_col.mV);
|
||||
for (U32 i = 0; i < cur_times.size(); ++i)
|
||||
{
|
||||
gGL.begin(LLRender::TRIANGLE_STRIP);
|
||||
gGL.vertex3f(last_p.mV[0], 0.f, 0.f);
|
||||
gGL.vertex3fv(last_p.mV);
|
||||
last_p.set((F32) i / (F32) cur_times.size(), cur_times[i]/max_time, 0.f);
|
||||
gGL.vertex3f(last_p.mV[0], 0.f, 0.f);
|
||||
gGL.vertex3fv(last_p.mV);
|
||||
gGL.end();
|
||||
}
|
||||
|
||||
gGL.flush();
|
||||
}
|
||||
|
||||
saveChart(label, "time", scratch);
|
||||
|
||||
//======================================
|
||||
// calls
|
||||
//======================================
|
||||
buffer.clear();
|
||||
|
||||
last_p.clear();
|
||||
|
||||
gGL.color3fv(base_col.mV);
|
||||
for (U32 i = 0; i < base_calls.size(); ++i)
|
||||
{
|
||||
gGL.begin(LLRender::TRIANGLE_STRIP);
|
||||
gGL.vertex3fv(last_p.mV);
|
||||
gGL.vertex3f(last_p.mV[0], 0.f, 0.f);
|
||||
last_p.set((F32) i / (F32) base_calls.size(), (F32)base_calls[i]/max_calls, 0.f);
|
||||
gGL.vertex3fv(last_p.mV);
|
||||
gGL.vertex3f(last_p.mV[0], 0.f, 0.f);
|
||||
gGL.end();
|
||||
}
|
||||
|
||||
gGL.flush();
|
||||
|
||||
{
|
||||
LLGLEnable blend(GL_BLEND);
|
||||
gGL.color3fv(cur_col.mV);
|
||||
last_p.clear();
|
||||
|
||||
for (U32 i = 0; i < cur_calls.size(); ++i)
|
||||
{
|
||||
gGL.begin(LLRender::TRIANGLE_STRIP);
|
||||
gGL.vertex3f(last_p.mV[0], 0.f, 0.f);
|
||||
gGL.vertex3fv(last_p.mV);
|
||||
last_p.set((F32) i / (F32) cur_calls.size(), (F32) cur_calls[i]/max_calls, 0.f);
|
||||
gGL.vertex3f(last_p.mV[0], 0.f, 0.f);
|
||||
gGL.vertex3fv(last_p.mV);
|
||||
gGL.end();
|
||||
|
||||
}
|
||||
|
||||
gGL.flush();
|
||||
}
|
||||
|
||||
saveChart(label, "calls", scratch);
|
||||
|
||||
//======================================
|
||||
// execution
|
||||
//======================================
|
||||
buffer.clear();
|
||||
|
||||
|
||||
gGL.color3fv(base_col.mV);
|
||||
U32 count = 0;
|
||||
U32 total_count = base_execution.size();
|
||||
|
||||
last_p.clear();
|
||||
|
||||
for (std::vector<LLSD::Real>::iterator iter = base_execution.begin(); iter != base_execution.end(); ++iter)
|
||||
{
|
||||
gGL.begin(LLRender::TRIANGLE_STRIP);
|
||||
gGL.vertex3fv(last_p.mV);
|
||||
gGL.vertex3f(last_p.mV[0], 0.f, 0.f);
|
||||
last_p.set((F32)count/(F32)total_count, *iter/max_execution, 0.f);
|
||||
gGL.vertex3fv(last_p.mV);
|
||||
gGL.vertex3f(last_p.mV[0], 0.f, 0.f);
|
||||
gGL.end();
|
||||
count++;
|
||||
}
|
||||
|
||||
last_p.clear();
|
||||
|
||||
{
|
||||
LLGLEnable blend(GL_BLEND);
|
||||
gGL.color3fv(cur_col.mV);
|
||||
count = 0;
|
||||
total_count = cur_execution.size();
|
||||
|
||||
for (std::vector<LLSD::Real>::iterator iter = cur_execution.begin(); iter != cur_execution.end(); ++iter)
|
||||
{
|
||||
gGL.begin(LLRender::TRIANGLE_STRIP);
|
||||
gGL.vertex3f(last_p.mV[0], 0.f, 0.f);
|
||||
gGL.vertex3fv(last_p.mV);
|
||||
last_p.set((F32)count/(F32)total_count, *iter/max_execution, 0.f);
|
||||
gGL.vertex3f(last_p.mV[0], 0.f, 0.f);
|
||||
gGL.vertex3fv(last_p.mV);
|
||||
gGL.end();
|
||||
count++;
|
||||
}
|
||||
|
||||
gGL.flush();
|
||||
}
|
||||
|
||||
saveChart(label, "execution", scratch);
|
||||
}
|
||||
|
||||
buffer.flush();
|
||||
|
||||
gGL.popMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
gGL.popMatrix();
|
||||
}
|
||||
|
||||
//static
|
||||
LLSD LLFastTimerView::analyzePerformanceLogDefault(std::istream& is)
|
||||
{
|
||||
|
|
@ -1132,7 +1498,8 @@ void LLFastTimerView::doAnalysisDefault(std::string baseline, std::string target
|
|||
base[label]["Samples"].asInteger());
|
||||
}
|
||||
|
||||
|
||||
exportCharts(baseline, target);
|
||||
|
||||
os.flush();
|
||||
os.close();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ private:
|
|||
static void doAnalysisMetrics(std::string baseline, std::string target, std::string output) ;
|
||||
static LLSD analyzeMetricPerformanceLog(std::istream& is) ;
|
||||
static LLSD analyzePerformanceLogDefault(std::istream& is) ;
|
||||
static void exportCharts(const std::string& base, const std::string& target);
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
|||
|
|
@ -127,6 +127,47 @@ static bool handleSetShaderChanged(const LLSD& newvalue)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool handleRenderPerfTestChanged(const LLSD& newvalue)
|
||||
{
|
||||
bool status = !newvalue.asBoolean();
|
||||
if (!status)
|
||||
{
|
||||
gPipeline.clearRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
|
||||
LLPipeline::RENDER_TYPE_WL_SKY,
|
||||
LLPipeline::RENDER_TYPE_GROUND,
|
||||
LLPipeline::RENDER_TYPE_TERRAIN,
|
||||
LLPipeline::RENDER_TYPE_GRASS,
|
||||
LLPipeline::RENDER_TYPE_TREE,
|
||||
LLPipeline::RENDER_TYPE_WATER,
|
||||
LLPipeline::RENDER_TYPE_PASS_GRASS,
|
||||
LLPipeline::RENDER_TYPE_HUD,
|
||||
LLPipeline::RENDER_TYPE_PARTICLES,
|
||||
LLPipeline::RENDER_TYPE_CLOUDS,
|
||||
LLPipeline::RENDER_TYPE_HUD_PARTICLES,
|
||||
LLPipeline::END_RENDER_TYPES);
|
||||
gPipeline.setRenderDebugFeatureControl(LLPipeline::RENDER_DEBUG_FEATURE_UI, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
|
||||
LLPipeline::RENDER_TYPE_WL_SKY,
|
||||
LLPipeline::RENDER_TYPE_GROUND,
|
||||
LLPipeline::RENDER_TYPE_TERRAIN,
|
||||
LLPipeline::RENDER_TYPE_GRASS,
|
||||
LLPipeline::RENDER_TYPE_TREE,
|
||||
LLPipeline::RENDER_TYPE_WATER,
|
||||
LLPipeline::RENDER_TYPE_PASS_GRASS,
|
||||
LLPipeline::RENDER_TYPE_HUD,
|
||||
LLPipeline::RENDER_TYPE_PARTICLES,
|
||||
LLPipeline::RENDER_TYPE_CLOUDS,
|
||||
LLPipeline::RENDER_TYPE_HUD_PARTICLES,
|
||||
LLPipeline::END_RENDER_TYPES);
|
||||
gPipeline.setRenderDebugFeatureControl(LLPipeline::RENDER_DEBUG_FEATURE_UI, false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool handleReleaseGLBufferChanged(const LLSD& newvalue)
|
||||
{
|
||||
if (gPipeline.isInit())
|
||||
|
|
@ -500,6 +541,7 @@ void settings_setup_listeners()
|
|||
gSavedSettings.getControl("RenderBakeSunlight")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2));
|
||||
gSavedSettings.getControl("RenderNoAlpha")->getSignal()->connect(boost::bind(&handleResetVertexBuffersChanged, _2));
|
||||
gSavedSettings.getControl("RenderAvatarVP")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
|
||||
gSavedSettings.getControl("RenderPerformanceTest")->getSignal()->connect(boost::bind(&handleRenderPerfTestChanged, _2));
|
||||
gSavedSettings.getControl("VertexShaderEnable")->getSignal()->connect(boost::bind(&handleSetShaderChanged, _2));
|
||||
gSavedSettings.getControl("RenderUIBuffer")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
|
||||
gSavedSettings.getControl("RenderSpecularResX")->getSignal()->connect(boost::bind(&handleReleaseGLBufferChanged, _2));
|
||||
|
|
|
|||
|
|
@ -402,6 +402,14 @@ void LLPipeline::init()
|
|||
toggleRenderType(RENDER_TYPE_GROUND);
|
||||
}
|
||||
|
||||
// make sure RenderPerformanceTest persists (hackity hack hack)
|
||||
// disables non-object rendering (UI, sky, water, etc)
|
||||
if (gSavedSettings.getBOOL("RenderPerformanceTest"))
|
||||
{
|
||||
gSavedSettings.setBOOL("RenderPerformanceTest", FALSE);
|
||||
gSavedSettings.setBOOL("RenderPerformanceTest", TRUE);
|
||||
}
|
||||
|
||||
mOldRenderDebugMask = mRenderDebugMask;
|
||||
|
||||
mBackfaceCull = TRUE;
|
||||
|
|
@ -5359,6 +5367,18 @@ BOOL LLPipeline::toggleRenderDebugFeatureControl(void* data)
|
|||
return gPipeline.hasRenderDebugFeatureMask(bit);
|
||||
}
|
||||
|
||||
void LLPipeline::setRenderDebugFeatureControl(U32 bit, bool value)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
gPipeline.mRenderDebugFeatureMask |= bit;
|
||||
}
|
||||
else
|
||||
{
|
||||
gPipeline.mRenderDebugFeatureMask &= !bit;
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void LLPipeline::setRenderScriptedBeacons(BOOL val)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -327,6 +327,7 @@ public:
|
|||
static BOOL toggleRenderTypeControlNegated(void* data);
|
||||
static BOOL toggleRenderDebugControl(void* data);
|
||||
static BOOL toggleRenderDebugFeatureControl(void* data);
|
||||
static void setRenderDebugFeatureControl(U32 bit, bool value);
|
||||
|
||||
static void setRenderParticleBeacons(BOOL val);
|
||||
static void toggleRenderParticleBeacons(void* data);
|
||||
|
|
|
|||
Loading…
Reference in New Issue