/* ----------------------------------------------------------------------------- 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; } //------------------------------------------------------------------------------