156 lines
4.4 KiB
C++
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;
|
|
}
|
|
//------------------------------------------------------------------------------
|