Files
Webcam/include/engine/gpu/gpu_render_display_list.cpp

156 lines
4.4 KiB
C++

/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "gpu/gpu_renderer.h"
#include "gpu/gpu_geometry.h"
#include "gpu/gpu_shader_object.h"
#include "gpu/gpu_draw_context.h"
#include "core/object.h"
#include "core/camera.h"
#include "core/geometry.h"
#include "log/log.h"
using namespace GS;
using namespace GS::GPU;
//------------------------------------------------------------------------------
#define ENABLE_PERFORMANCE_TOOLS
#ifdef ENABLE_PERFORMANCE_TOOLS
#define _ProgramCacheMiss ++gpu_stats.prg_change;
#define _DisplayListCacheMiss ++gpu_stats.dls_change;
#define _MaterialCacheMiss ++gpu_stats.mat_change;
#define _ItemCacheMiss ++gpu_stats.item_change;
#define _SetPerfWire if (performance_tools.show_wireframe) SetFillMode(FillWireframe);
#define _UnsetPerfWire if (performance_tools.show_wireframe) SetFillMode(FillSolid);
#else
#define _ProgramCacheMiss
#define _DisplayListCacheMiss
#define _MaterialCacheMiss
#define _ItemCacheMiss
#define _SetPerfWire
#define _UnsetPerfWire
#endif
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Renderer::ResetDisplayListCache()
{
if (dls_cache.dls)
SetDisplayList(NULL);
dls_cache.dls = NULL;
if (dls_cache.mat)
UnsetMaterial(*dls_cache.mat, dls_cache.ctx);
dls_cache.mat = NULL;
if (dls_cache.shd)
SetShaderProgram(NULL, dls_cache.shd);
dls_cache.shd = NULL;
dls_cache.item = NULL;
}
bool Renderer::SetDrawContext(DisplayList &dls, const Core::Item &item, const DrawContext &dc)
{
Material *mat = dls.material.IsValid() ? (Material *)dls.material.c_ptr() : NULL;
if (!mat || !mat->shader)
return false;
Shader *shd = mat->shader->variants[dc.ctx.variant];
if (!shd)
return false;
#define ProgramChange (1 << 0)
#define DisplayListChange (1 << 1)
#define MaterialChange (1 << 2)
#define ItemChange (1 << 3)
#define OpacityChange (1 << 4)
uint change_mask = 0;
change_mask |= (shd != dls_cache.shd) ? ProgramChange : 0;
change_mask |= (&dls != dls_cache.dls) ? DisplayListChange : 0;
change_mask |= (mat != dls_cache.mat) ? MaterialChange : 0;
change_mask |= (&item != dls_cache.item) ? ItemChange : 0;
change_mask |= (item.opacity != dls_cache.opacity) ? OpacityChange : 0;
if (change_mask & ProgramChange)
{
if (!SetShaderProgram(shd, dls_cache.shd))
return false;
_ProgramCacheMiss
}
if (change_mask & ProgramChange)
shd->SetConstantInputs();
if (change_mask & DisplayListChange)
{
SetDisplayList(&dls);
_DisplayListCacheMiss
}
if (change_mask & MaterialChange)
{
if (dls_cache.mat)
UnsetMaterial(*dls_cache.mat, dc.ctx);
SetMaterial(*mat, dc.ctx, asbool(item.opacity < 1.f));
_MaterialCacheMiss
}
// Program inputs.
if (change_mask & ProgramChange)
{
shd->SetRendererInputs(*this, mat);
if (dc.light)
shd->SetLightInputs(*this, *view_item, *dc.light);
}
if (change_mask & (ProgramChange | MaterialChange | OpacityChange))
shd->SetMaterialOpacityInputs(*mat, item.opacity);
if (change_mask & (ProgramChange | MaterialChange))
{
shd->SetMaterialInputs(*mat);
shd->SetTextureInputs();
}
if (change_mask & (ProgramChange | DisplayListChange))
shd->SetVertexStreamInputs(dls);
if (change_mask & (ProgramChange | ItemChange))
{
shd->SetTransformInputs(m_projection, m_view, m_iview, &m_world, &m_iworld);
shd->SetPreviousTransformInputs(m_projection, m_previous_iview, &m_previous_world);
_ItemCacheMiss
}
if (change_mask & (ProgramChange | DisplayListChange | ItemChange))
if (Core::Skin *skin = ((Core::Object &)item).GetSkin())
shd->SetSkinInputs(dls, *skin);
shd->CommitInputs();
// Sync cache.
dls_cache.ctx = dc.ctx;
dls_cache.shd = shd;
dls_cache.mat = mat;
dls_cache.dls = &dls;
dls_cache.item = &item;
dls_cache.opacity = item.opacity;
return true;
}
void Renderer::DrawDisplayListCached(DisplayList &dls, const Core::Item &item, const DrawContext &dc)
{
if (!SetDrawContext(dls, item, dc))
return;
// Draw.
_SetPerfWire
dls.Draw();
_UnsetPerfWire
stats.list_drawn++;
stats.triangle_drawn += dls.index_count / 3;
}
//------------------------------------------------------------------------------