[Aqsis-commits] [SCM] Aqsis Renderer branch, master, updated. Release_1.6.0_Phase2-174-ge4efeea
Brought to you by:
ltatkinson,
pgregory
From: Chris F. <c4...@us...> - 2010-02-28 06:48:18
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Aqsis Renderer". The branch, master has been updated via e4efeea83b5f462704387f3fa8b3eee66c063d3a (commit) via 9f2edfdcfc538153133bfa39540968373c6b15f5 (commit) from 16855f03d614e70ce0edefc67cd10d77855df827 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit e4efeea83b5f462704387f3fa8b3eee66c063d3a Author: Chris Foster <chr...@gm...> Date: Sun Feb 28 15:41:34 2010 +1000 Optimization: intrusive_ptr rather than shared_ptr shared_ptr is needlessly inefficient for small objects which will be created in large numbers, because (1) it requires a separate heap allocated reference count and (2) the required storage is larger than a pointer. This change replaces all use of shared_ptr with intrusive_ptr and introduces a non-virtual counted base, "RefCounted" to ease the creation of objects with reference counts. The performance improvements for the tenpatch scene are almost 10%. diff --git a/prototypes/newcore/attributes.h b/prototypes/newcore/attributes.h index 0c1b3a3..744e3fd 100644 --- a/prototypes/newcore/attributes.h +++ b/prototypes/newcore/attributes.h @@ -27,7 +27,7 @@ struct Attributes { float shadingRate; ///< Desired micropoly area bool smoothShading; ///< Type of shading interpolation - boost::shared_ptr<Shader> surfaceShader; ///< surface shader + ShaderPtr surfaceShader; ///< surface shader Attributes() : shadingRate(1), diff --git a/prototypes/newcore/filters.h b/prototypes/newcore/filters.h index 08f53b7..5fdeee9 100644 --- a/prototypes/newcore/filters.h +++ b/prototypes/newcore/filters.h @@ -22,12 +22,10 @@ #include "util.h" // for Vec2 -#include <boost/shared_ptr.hpp> - /// Filter functor class /// /// Includes information about the width & separability of the filter. -class Filter +class Filter : public RefCounted { private: Vec2 m_width; @@ -59,7 +57,7 @@ class Filter }; -typedef boost::shared_ptr<Filter> FilterPtr; +typedef boost::intrusive_ptr<Filter> FilterPtr; FilterPtr makeBoxFilter(const Vec2& width); diff --git a/prototypes/newcore/geometry.h b/prototypes/newcore/geometry.h index aa70287..37e46e2 100644 --- a/prototypes/newcore/geometry.h +++ b/prototypes/newcore/geometry.h @@ -29,6 +29,8 @@ class Options; class Attributes; class TessControl; +typedef boost::intrusive_ptr<Geometry> GeometryPtr; +typedef boost::intrusive_ptr<Grid> GridPtr; /// Tessellation context for geometric split/dice /// @@ -49,11 +51,11 @@ class TessellationContext /// Push some geometry into the render pipeline. /// The results from splitting operations go here. - virtual void push(const boost::shared_ptr<Geometry>& geom) = 0; + virtual void push(const GeometryPtr& geom) = 0; /// Push a grid into the render pipeline. /// The results from geometry dicing go here. - virtual void push(const boost::shared_ptr<Grid>& grid) = 0; + virtual void push(const GridPtr& grid) = 0; /// Return the renderer option state virtual const Options& options() = 0; @@ -68,7 +70,7 @@ class TessellationContext /// Abstract piece of geometry to be rendered -class Geometry +class Geometry : public RefCounted { public: // Return the number of values required to represent a primvar of each diff --git a/prototypes/newcore/grid.h b/prototypes/newcore/grid.h index bc62fb5..ea77187 100644 --- a/prototypes/newcore/grid.h +++ b/prototypes/newcore/grid.h @@ -29,7 +29,7 @@ enum GridType GridType_QuadSimple }; -class Grid +class Grid : public RefCounted { private: GridType m_type; @@ -49,6 +49,8 @@ class Grid virtual ~Grid() {} }; +typedef boost::intrusive_ptr<Grid> GridPtr; + //------------------------------------------------------------------------------ /// A 2D grid of quadrilateral micro polygons @@ -57,12 +59,12 @@ class QuadGrid : public Grid private: int m_nu; int m_nv; - boost::shared_ptr<GridStorage> m_storage; + GridStoragePtr m_storage; public: class Iterator; - QuadGrid(int nu, int nv, boost::shared_ptr<GridStorage> storage) + QuadGrid(int nu, int nv, const GridStoragePtr& storage) : Grid(GridType_Quad), m_nu(nu), m_nv(nv), diff --git a/prototypes/newcore/gridstorage.h b/prototypes/newcore/gridstorage.h index d10eeb0..e8be2f5 100644 --- a/prototypes/newcore/gridstorage.h +++ b/prototypes/newcore/gridstorage.h @@ -21,7 +21,6 @@ #define GRIDVAR_H_INCLUDED #include <boost/scoped_array.hpp> -#include <boost/shared_ptr.hpp> #include <boost/noncopyable.hpp> #include "arrayview.h" @@ -37,7 +36,7 @@ /// access to each variable storage based on the index within the grid. In /// order to allow for efficient allocation, GridStorage should be constructed /// via the specialized GridStorageBuilder object. -class GridStorage +class GridStorage : public RefCounted { private: boost::scoped_array<float> m_storage; @@ -167,6 +166,8 @@ class GridStorage } }; +typedef boost::intrusive_ptr<GridStorage> GridStoragePtr; + //------------------------------------------------------------------------------ /// Object to collect arguments necessary to build a GridStorage object. @@ -247,7 +248,7 @@ class GridStorageBuilder : boost::noncopyable } /// Build the grid storage using the current set of variables. - boost::shared_ptr<GridStorage> build(int nverts) + GridStoragePtr build(int nverts) { std::sort(m_vars.begin(), m_vars.end()); // Uniqueify the vars. Any duplicates coming from the geometry @@ -281,7 +282,7 @@ class GridStorageBuilder : boost::noncopyable } // Ok, now that we have all our vars, it's possible to create the // storage space. - return boost::shared_ptr<GridStorage>( + return GridStoragePtr( new GridStorage(m_vars.begin(), m_vars.end(), nverts)); } }; diff --git a/prototypes/newcore/gridstorage_test.cpp b/prototypes/newcore/gridstorage_test.cpp index 9b634e9..3d5afc8 100644 --- a/prototypes/newcore/gridstorage_test.cpp +++ b/prototypes/newcore/gridstorage_test.cpp @@ -32,7 +32,7 @@ BOOST_AUTO_TEST_CASE(GridStorageBuilder_unique_test) builder.add(Stdvar::Ci, GridStorage::Uniform); builder.add(Stdvar::P, GridStorage::Uniform); - boost::shared_ptr<GridStorage> stor = builder.build(10); + GridStoragePtr stor = builder.build(10); BOOST_CHECK_EQUAL(stor->varSet().size(), 3); BOOST_CHECK(stor->varSet().contains(Stdvar::P)); BOOST_CHECK(stor->varSet().contains(Stdvar::Cs)); @@ -48,7 +48,7 @@ BOOST_AUTO_TEST_CASE(GridStorageBuilder_precedence_test) builder.setFromGeom(); // then as varying, which should override the uniform case. builder.add(Stdvar::P, GridStorage::Varying); - boost::shared_ptr<GridStorage> stor = builder.build(10); + GridStoragePtr stor = builder.build(10); BOOST_REQUIRE_EQUAL(stor->varSet().size(), 1); BOOST_CHECK(!stor->get(0).uniform()); } @@ -60,7 +60,7 @@ BOOST_AUTO_TEST_CASE(GridStorageBuilder_precedence_test) builder.setFromGeom(); // then as uniform, which should override the varying case. builder.add(Stdvar::P, GridStorage::Uniform); - boost::shared_ptr<GridStorage> stor = builder.build(10); + GridStoragePtr stor = builder.build(10); BOOST_REQUIRE_EQUAL(stor->varSet().size(), 1); BOOST_CHECK(stor->get(0).uniform()); } @@ -71,7 +71,7 @@ BOOST_AUTO_TEST_CASE(GridStorage_maxAggregateSize_test) GridStorageBuilder builder; builder.add(Stdvar::P, GridStorage::Varying); builder.add(VarSpec(VarSpec::Float, 42, ustring("f")), GridStorage::Varying); - boost::shared_ptr<GridStorage> stor = builder.build(10); + GridStoragePtr stor = builder.build(10); BOOST_CHECK_EQUAL(stor->maxAggregateSize(), 42); } @@ -80,7 +80,7 @@ BOOST_AUTO_TEST_CASE(GridStorage_P_test) { GridStorageBuilder builder; builder.add(Stdvar::P, GridStorage::Varying); - boost::shared_ptr<GridStorage> stor = builder.build(10); + GridStoragePtr stor = builder.build(10); // Check that P is present. BOOST_CHECK(stor->P()); } @@ -91,7 +91,7 @@ BOOST_AUTO_TEST_CASE(GridStorage_get_test) builder.add(Stdvar::P, GridStorage::Varying); VarSpec f(VarSpec::Float, 42, ustring("f")); builder.add(f, GridStorage::Varying); - boost::shared_ptr<GridStorage> stor = builder.build(10); + GridStoragePtr stor = builder.build(10); // Check that P and f are present BOOST_CHECK(stor->get(Stdvar::P)); BOOST_CHECK(stor->get(f)); diff --git a/prototypes/newcore/primvar.h b/prototypes/newcore/primvar.h index 6b42998..bed7060 100644 --- a/prototypes/newcore/primvar.h +++ b/prototypes/newcore/primvar.h @@ -24,7 +24,6 @@ #include <stdexcept> #include <vector> -#include <boost/shared_ptr.hpp> #include <boost/scoped_array.hpp> #include "util.h" @@ -131,7 +130,7 @@ struct IclassStorage //------------------------------------------------------------------------------ -class PrimvarStorage +class PrimvarStorage : public RefCounted { private: boost::scoped_array<float> m_storage; @@ -246,6 +245,8 @@ class PrimvarStorage } }; +typedef boost::intrusive_ptr<PrimvarStorage> PrimvarStoragePtr; + //------------------------------------------------------------------------------ class PrimvarStorageBuilder @@ -275,7 +276,7 @@ class PrimvarStorageBuilder m_vars.push_back(PvarInitSpec(var, data, srcLength)); } - boost::shared_ptr<PrimvarStorage> build(const IclassStorage& storCount) + PrimvarStoragePtr build(const IclassStorage& storCount) { for(int i = 0, nvars = m_vars.size(); i < nvars; ++i) { @@ -301,7 +302,7 @@ class PrimvarStorageBuilder // s, t // std::sort(m_vars.begin(), m_vars.end()); - return boost::shared_ptr<PrimvarStorage>( + return PrimvarStoragePtr( new PrimvarStorage(m_vars.begin(), m_vars.end(), storCount)); } }; diff --git a/prototypes/newcore/primvar_test.cpp b/prototypes/newcore/primvar_test.cpp index 02dc992..e7b91b4 100644 --- a/prototypes/newcore/primvar_test.cpp +++ b/prototypes/newcore/primvar_test.cpp @@ -88,7 +88,7 @@ int main() GridStorageBuilder gridBuilder; GridvarList gvarSet(pvarStorage.varList()); const int nu = 5, nv = 5; - boost::shared_ptr<GridStorage> gvarStorage = gridBuilder.build(nu*nv); + GridStoragePtr gvarStorage = gridBuilder.build(nu*nv); // Create some space to store the variable temporaries. int maxAgg = gvarStorage.maxAggregateSize(); diff --git a/prototypes/newcore/renderer.cpp b/prototypes/newcore/renderer.cpp index 6afc29b..9b1d772 100644 --- a/prototypes/newcore/renderer.cpp +++ b/prototypes/newcore/renderer.cpp @@ -35,20 +35,20 @@ class Renderer::GeomHolder : public RefCounted { private: - boost::shared_ptr<Geometry> m_geom; ///< Pointer to geometry + GeometryPtr m_geom; ///< Pointer to geometry int m_splitCount; ///< Number of times the geometry has been split Box m_bound; ///< Bound in camera coordinates Attributes* m_attrs; ///< Surface attribute state public: - GeomHolder(const boost::shared_ptr<Geometry>& geom, Attributes* attrs) + GeomHolder(const GeometryPtr& geom, Attributes* attrs) : m_geom(geom), m_splitCount(0), m_bound(geom->bound()), m_attrs(attrs) { } - GeomHolder(const boost::shared_ptr<Geometry>& geom, + GeomHolder(const GeometryPtr& geom, const GeomHolder& parent) : m_geom(geom), m_splitCount(parent.m_splitCount+1), @@ -117,14 +117,14 @@ class TessellationContextImpl : public TessellationContext tessControl.tessellate(m_parentGeom->geom(), *this); } - virtual void push(const boost::shared_ptr<Geometry>& geom) + virtual void push(const GeometryPtr& geom) { Renderer::GeomHolderPtr holder( new Renderer::GeomHolder(geom, *m_parentGeom)); m_renderer.push(holder); } - virtual void push(const boost::shared_ptr<Grid>& grid) + virtual void push(const GridPtr& grid) { // Fill in any grid data which didn't get filled in by the surface // during the dicing stage. @@ -438,8 +438,7 @@ void Renderer::push(const GeomHolderPtr& geom) // Push a grid onto the render queue -void Renderer::push(const boost::shared_ptr<Grid>& grid, - const GeomHolder& parentSurface) +void Renderer::push(const GridPtr& grid, const GeomHolder& parentSurface) { // For now, just rasterize it directly. switch(grid->type()) @@ -500,7 +499,7 @@ Renderer::Renderer(const Options& opts, const Mat4& camToScreen, // leaking (SurfaceQueue destructor is called implicitly) Renderer::~Renderer() { } -void Renderer::add(const boost::shared_ptr<Geometry>& geom, +void Renderer::add(const GeometryPtr& geom, Attributes& attrs) { // TODO: Transform to camera space? diff --git a/prototypes/newcore/renderer.h b/prototypes/newcore/renderer.h index 9993c15..a3dc0cc 100644 --- a/prototypes/newcore/renderer.h +++ b/prototypes/newcore/renderer.h @@ -24,8 +24,6 @@ #include <queue> #include <vector> -#include <boost/intrusive_ptr.hpp> -#include <boost/shared_ptr.hpp> #include <boost/scoped_array.hpp> #include <boost/scoped_ptr.hpp> @@ -40,6 +38,8 @@ class QuadGridSimple; class TessellationContextImpl; class SampleStorage; +typedef boost::intrusive_ptr<Geometry> GeometryPtr; +typedef boost::intrusive_ptr<Grid> GridPtr; //----------------------------------------------------------------------------- struct OutvarSpec : public VarSpec @@ -92,7 +92,7 @@ class Renderer ~Renderer(); /// Add geometry - void add(const boost::shared_ptr<Geometry>& geom, Attributes& attrs); + void add(const GeometryPtr& geom, Attributes& attrs); /// Render all surfaces and save resulting image. void render(); @@ -120,7 +120,7 @@ class Renderer void saveImages(const std::string& baseFileName); void push(const GeomHolderPtr& geom); - void push(const boost::shared_ptr<Grid>& grid, + void push(const GridPtr& grid, const GeomHolder& parentSurface); template<typename GridT, typename PolySamplerT> diff --git a/prototypes/newcore/scenes/default.cpp b/prototypes/newcore/scenes/default.cpp index 116bcf7..454a9ab 100644 --- a/prototypes/newcore/scenes/default.cpp +++ b/prototypes/newcore/scenes/default.cpp @@ -64,7 +64,7 @@ void addQuadMesh(Attributes& attrs, Renderer& r, const Mat4& otow, builder.add(Primvar::Cs, Cs_stor, 12); } IclassStorage storReq(1,4,4,4,4); - boost::shared_ptr<Geometry> patch(new Patch(builder.build(storReq))); + GeometryPtr patch(new Patch(builder.build(storReq))); patch->transform(otow); r.add(patch, attrs); vertices += 4; diff --git a/prototypes/newcore/scenes/tenpatch.cpp b/prototypes/newcore/scenes/tenpatch.cpp index fd038a7..8e34a65 100644 --- a/prototypes/newcore/scenes/tenpatch.cpp +++ b/prototypes/newcore/scenes/tenpatch.cpp @@ -22,7 +22,7 @@ #include "simple.h" static -boost::shared_ptr<Geometry> createPatch(const Vec3& a, const Vec3& b, +GeometryPtr createPatch(const Vec3& a, const Vec3& b, const Vec3& c, const Vec3& d, const Mat4& trans = Mat4()) { @@ -33,8 +33,8 @@ boost::shared_ptr<Geometry> createPatch(const Vec3& a, const Vec3& b, }; builder.add(Primvar::P, P, array_len(P)); IclassStorage storReq(1,4,4,4,4); - boost::shared_ptr<Geometry> patch(new Patch(builder.build(storReq))); -// boost::shared_ptr<Geometry> patch(new PatchSimple(a,b,c,d)); + GeometryPtr patch(new Patch(builder.build(storReq))); +// GeometryPtr patch(new PatchSimple(a,b,c,d)); patch->transform(trans); return patch; } diff --git a/prototypes/newcore/shader.cpp b/prototypes/newcore/shader.cpp index ee248c1..99a6ea3 100644 --- a/prototypes/newcore/shader.cpp +++ b/prototypes/newcore/shader.cpp @@ -257,14 +257,14 @@ class ShowPolys : public IOVarHolder //------------------------------------------------------------------------------ -boost::shared_ptr<Shader> createShader(const char* name) +ShaderPtr createShader(const char* name) { if(name == std::string("test")) - return boost::shared_ptr<Shader>(new TestShader()); + return ShaderPtr(new TestShader()); else if(name == std::string("showgrids")) - return boost::shared_ptr<Shader>(new ShowGrids()); + return ShaderPtr(new ShowGrids()); else if(name == std::string("showpolys")) - return boost::shared_ptr<Shader>(new ShowPolys()); - return boost::shared_ptr<Shader>(new DefaultSurface()); + return ShaderPtr(new ShowPolys()); + return ShaderPtr(new DefaultSurface()); } diff --git a/prototypes/newcore/shader.h b/prototypes/newcore/shader.h index 9f995d8..8068f0c 100644 --- a/prototypes/newcore/shader.h +++ b/prototypes/newcore/shader.h @@ -22,12 +22,12 @@ #include "varspec.h" -#include <boost/shared_ptr.hpp> +#include "util.h" class Grid; /// A simplistic shader interface -class Shader +class Shader : public RefCounted { public: /// Get the set of input variables used by the shader. @@ -41,8 +41,10 @@ class Shader virtual ~Shader() {} }; +typedef boost::intrusive_ptr<Shader> ShaderPtr; + // Create one of the builtin shaders. -boost::shared_ptr<Shader> createShader(const char* name); +ShaderPtr createShader(const char* name); #endif // SHADER_H_INCLUDED diff --git a/prototypes/newcore/simple.h b/prototypes/newcore/simple.h index 0030d8f..6099f45 100644 --- a/prototypes/newcore/simple.h +++ b/prototypes/newcore/simple.h @@ -87,7 +87,7 @@ class PatchSimple : public Geometry void dice(int uRes, int vRes, TessellationContext& tessCtx) const { - boost::shared_ptr<QuadGridSimple> + boost::intrusive_ptr<QuadGridSimple> grid(new QuadGridSimple(uRes, vRes)); float dv = 1.0f/(vRes-1); float du = 1.0f/(uRes-1); @@ -112,9 +112,9 @@ class PatchSimple : public Geometry // c---d Vec3 ab = 0.5f*(m_P[0] + m_P[1]); Vec3 cd = 0.5f*(m_P[2] + m_P[3]); - tessCtx.push(boost::shared_ptr<Geometry>( + tessCtx.push(GeometryPtr( new PatchSimple(m_P[0], ab, m_P[2], cd))); - tessCtx.push(boost::shared_ptr<Geometry>( + tessCtx.push(GeometryPtr( new PatchSimple(ab, m_P[1], cd, m_P[3]))); } else @@ -125,10 +125,10 @@ class PatchSimple : public Geometry // c---d Vec3 ac = 0.5f*(m_P[0] + m_P[2]); Vec3 bd = 0.5f*(m_P[1] + m_P[3]); - tessCtx.push(boost::shared_ptr<Geometry>( - new PatchSimple( m_P[0], m_P[1], ac, bd))); - tessCtx.push(boost::shared_ptr<Geometry>( - new PatchSimple( ac, bd, m_P[2], m_P[3]))); + tessCtx.push(GeometryPtr( + new PatchSimple(m_P[0], m_P[1], ac, bd))); + tessCtx.push(GeometryPtr( + new PatchSimple(ac, bd, m_P[2], m_P[3]))); } } diff --git a/prototypes/newcore/surfaces.h b/prototypes/newcore/surfaces.h index 4891eab..355736b 100644 --- a/prototypes/newcore/surfaces.h +++ b/prototypes/newcore/surfaces.h @@ -33,7 +33,7 @@ class Patch : public Geometry { private: - boost::shared_ptr<PrimvarStorage> m_vars; + PrimvarStoragePtr m_vars; // uv coordinates for corners of the base patch. const float m_uMin, m_uMax; @@ -47,8 +47,8 @@ class Patch : public Geometry GridStorageBuilder& builder = tessCtx.gridStorageBuilder(); // Add all the primvars to the grid builder.add(m_vars->varSet()); - boost::shared_ptr<GridStorage> storage = builder.build(nu*nv); - boost::shared_ptr<QuadGrid> grid(new QuadGrid(nu, nv, storage)); + GridStoragePtr storage = builder.build(nu*nv); + boost::intrusive_ptr<QuadGrid> grid(new QuadGrid(nu, nv, storage)); // Create some space to store the variable temporaries. int maxAgg = storage->maxAggregateSize(); @@ -113,10 +113,10 @@ class Patch : public Geometry // | | | // c---d float uMid = 0.5*(m_uMin + m_uMax); - tessCtx.push(boost::shared_ptr<Geometry>( - new Patch(m_vars, m_uMin, uMid, m_vMin, m_vMax))); - tessCtx.push(boost::shared_ptr<Geometry>( - new Patch(m_vars, uMid, m_uMax, m_vMin, m_vMax))); + tessCtx.push(GeometryPtr(new Patch(m_vars, m_uMin, + uMid, m_vMin, m_vMax))); + tessCtx.push(GeometryPtr(new Patch(m_vars, uMid, + m_uMax, m_vMin, m_vMax))); } else { @@ -125,10 +125,10 @@ class Patch : public Geometry // |---| // c---d float vMid = 0.5*(m_vMin + m_vMax); - tessCtx.push(boost::shared_ptr<Geometry>( - new Patch(m_vars, m_uMin, m_uMax, m_vMin, vMid))); - tessCtx.push(boost::shared_ptr<Geometry>( - new Patch(m_vars, m_uMin, m_uMax, vMid, m_vMax))); + tessCtx.push(GeometryPtr(new Patch(m_vars, m_uMin, + m_uMax, m_vMin, vMid))); + tessCtx.push(GeometryPtr(new Patch(m_vars, m_uMin, + m_uMax, vMid, m_vMax))); } } @@ -141,7 +141,7 @@ class Patch : public Geometry d = bilerp(P[0], P[1], P[2], P[3], m_uMax, m_vMax); } - Patch(boost::shared_ptr<PrimvarStorage> vars, + Patch(const PrimvarStoragePtr& vars, float uMin, float uMax, float vMin, float vMax) : m_vars(vars), m_uMin(uMin), m_uMax(uMax), @@ -149,7 +149,7 @@ class Patch : public Geometry { } public: - Patch(boost::shared_ptr<PrimvarStorage> vars) + Patch(const PrimvarStoragePtr& vars) : m_vars(vars), m_uMin(0), m_uMax(1), m_vMin(0), m_vMax(1) diff --git a/prototypes/newcore/util.h b/prototypes/newcore/util.h index 90efc8c..db9a1b6 100644 --- a/prototypes/newcore/util.h +++ b/prototypes/newcore/util.h @@ -32,6 +32,7 @@ #include <boost/utility/enable_if.hpp> #include <boost/type_traits/arithmetic_traits.hpp> #include <boost/type_traits/is_base_of.hpp> +#include <boost/intrusive_ptr.hpp> // The distinction here is only due to the layout of the // win32libs copy of OpenEXR. @@ -254,7 +255,7 @@ template<typename T, size_t sz> int array_len(T (&a)[sz]) { return sz; } inline void nullDeleter(const void*) { } -/// Reference counted base for use with boost::intrusive_ptr. +/// Reference counted base mixin for use with boost::intrusive_ptr. /// /// This is a non-virtual implementation for maximum efficiency. class RefCounted @@ -262,7 +263,13 @@ class RefCounted private: mutable int m_refCount; public: - int refCount() const { return m_refCount; } + RefCounted() : m_refCount(0) {} + + /// Copying does *not* copy the reference count! + RefCounted(const RefCounted& /*r*/) : m_refCount(0) {} + RefCounted& operator=(const RefCounted& /*r*/) { return *this; } + + int useCount() const { return m_refCount; } int incRef() const { return ++m_refCount; } int decRef() const { return --m_refCount; } }; commit 9f2edfdcfc538153133bfa39540968373c6b15f5 Author: Chris Foster <chr...@gm...> Date: Sun Feb 28 01:12:09 2010 +1000 Refactor GeomHolder with deformation in mind. This change makes GeomHolder into a class, with the idea that it will gain slightly more complicated behaviour as deformation motion blur is implemented. I'm using intrusive_ptr here because if shared_ptr is used, we end up with a few percent performance hit (tested at ~4% percent on core2) with the tenpatch test scene. diff --git a/prototypes/newcore/geometry.h b/prototypes/newcore/geometry.h index 2810d3c..aa70287 100644 --- a/prototypes/newcore/geometry.h +++ b/prototypes/newcore/geometry.h @@ -119,7 +119,7 @@ class TessControl { public: /// Tessellate the geometry & push the results back to the context. - virtual void tessellate(Geometry& geom, + virtual void tessellate(const Geometry& geom, TessellationContext& tessContext) const = 0; virtual ~TessControl() {}; @@ -140,10 +140,10 @@ class SurfaceDicer : public TessControl public: SurfaceDicer(int nu, int nv) : m_nu(nu), m_nv(nv) {} - virtual void tessellate(Geometry& geom, + virtual void tessellate(const Geometry& geom, TessellationContext& tessContext) const { - GeomT& g = static_cast<GeomT&>(geom); + const GeomT& g = static_cast<const GeomT&>(geom); g.dice(m_nu, m_nv, tessContext); } }; @@ -159,10 +159,10 @@ class SurfaceSplitter : public TessControl SurfaceSplitter(bool splitDirectionU) : m_splitDirectionU(splitDirectionU) {} - virtual void tessellate(Geometry& geom, + virtual void tessellate(const Geometry& geom, TessellationContext& tessContext) const { - GeomT& g = static_cast<GeomT&>(geom); + const GeomT& g = static_cast<const GeomT&>(geom); g.split(m_splitDirectionU, tessContext); } }; diff --git a/prototypes/newcore/renderer.cpp b/prototypes/newcore/renderer.cpp index 40337d5..6afc29b 100644 --- a/prototypes/newcore/renderer.cpp +++ b/prototypes/newcore/renderer.cpp @@ -32,22 +32,40 @@ /// Container for geometry and geometry metadata -struct Renderer::SurfaceHolder +class Renderer::GeomHolder : public RefCounted { - boost::shared_ptr<Geometry> geom; ///< Pointer to geometry - int splitCount; ///< Number of times the geometry has been split - Box bound; ///< Bound in camera coordinates - Attributes* attrs; ///< Surface attribute state - - SurfaceHolder(const boost::shared_ptr<Geometry>& geom, - int splitCount, Box bound, Attributes* attrs) - : geom(geom), - splitCount(splitCount), - bound(bound), - attrs(attrs) - { } + private: + boost::shared_ptr<Geometry> m_geom; ///< Pointer to geometry + int m_splitCount; ///< Number of times the geometry has been split + Box m_bound; ///< Bound in camera coordinates + Attributes* m_attrs; ///< Surface attribute state + + public: + GeomHolder(const boost::shared_ptr<Geometry>& geom, Attributes* attrs) + : m_geom(geom), + m_splitCount(0), + m_bound(geom->bound()), + m_attrs(attrs) + { } + + GeomHolder(const boost::shared_ptr<Geometry>& geom, + const GeomHolder& parent) + : m_geom(geom), + m_splitCount(parent.m_splitCount+1), + m_bound(geom->bound()), + m_attrs(parent.m_attrs) + { } + + Geometry& geom() { return *m_geom; } + const Geometry& geom() const { return *m_geom; } + //bool isDeforming() const { return true; } + int splitCount() const { return m_splitCount; } + Box& bound() { return m_bound; } + Attributes& attrs() { return *m_attrs; } + const Attributes& attrs() const { return *m_attrs; } }; + /// Ordering functor for surfaces in the render queue class Renderer::SurfaceOrder { @@ -57,17 +75,17 @@ class Renderer::SurfaceOrder public: SurfaceOrder() : m_bucketHeight(16) {} - bool operator()(const SurfaceHolder& a, - const SurfaceHolder& b) const + bool operator()(const GeomHolderPtr& a, + const GeomHolderPtr& b) const { - float ya = a.bound.min.y; - float yb = b.bound.min.y; + float ya = a->bound().min.y; + float yb = b->bound().min.y; if(ya < yb - m_bucketHeight) return true; else if(yb < ya - m_bucketHeight) return false; else - return a.bound.min.x < b.bound.min.x; + return a->bound().min.x < b->bound().min.x; } }; @@ -80,28 +98,30 @@ class TessellationContextImpl : public TessellationContext private: Renderer& m_renderer; GridStorageBuilder m_builder; - const Renderer::SurfaceHolder* m_parentSurface; + const Renderer::GeomHolder* m_parentGeom; public: TessellationContextImpl(Renderer& renderer) : m_renderer(renderer), m_builder(), - m_parentSurface(0) + m_parentGeom(0) { } - void setParent(Renderer::SurfaceHolder& parent) + void setParent(const Renderer::GeomHolder& parent) { - m_parentSurface = &parent; + m_parentGeom = &parent; } virtual void invokeTessellator(TessControl& tessControl) { - tessControl.tessellate(*(m_parentSurface->geom), *this); + tessControl.tessellate(m_parentGeom->geom(), *this); } virtual void push(const boost::shared_ptr<Geometry>& geom) { - m_renderer.push(geom, *m_parentSurface); + Renderer::GeomHolderPtr holder( + new Renderer::GeomHolder(geom, *m_parentGeom)); + m_renderer.push(holder); } virtual void push(const boost::shared_ptr<Grid>& grid) @@ -136,7 +156,7 @@ class TessellationContextImpl : public TessellationContext copy(I, P, stor.nverts()); } // Push the grid into the render pipeline - m_renderer.push(grid, *m_parentSurface); + m_renderer.push(grid, *m_parentGeom); } virtual const Options& options() @@ -145,7 +165,7 @@ class TessellationContextImpl : public TessellationContext } virtual const Attributes& attributes() { - return *(m_parentSurface->attrs); + return m_parentGeom->attrs(); } virtual GridStorageBuilder& gridStorageBuilder() @@ -158,11 +178,11 @@ class TessellationContextImpl : public TessellationContext m_builder.clear(); // TODO: AOV stuff shouldn't be conditional on surfaceShader // existing. - if(m_parentSurface->attrs->surfaceShader) + if(m_parentGeom->attrs().surfaceShader) { // Renderer arbitrary output vars const OutvarSet& aoVars = m_renderer.m_outVars; - const Shader& shader = *m_parentSurface->attrs->surfaceShader; + const Shader& shader = *m_parentGeom->attrs().surfaceShader; const VarSet& inVars = shader.inputVars(); // P is guaranteed to be dice by the geometry. m_builder.add(Stdvar::P, GridStorage::Varying); @@ -385,13 +405,11 @@ void Renderer::saveImages(const std::string& baseFileName) // Guts of the renderer /// Push geometry into the render queue -void Renderer::push(const boost::shared_ptr<Geometry>& geom, - const SurfaceHolder& parentSurface) +void Renderer::push(const GeomHolderPtr& geom) { - int splitCount = parentSurface.splitCount + 1; // Get bound in camera space. - Box bound = geom->bound(); - if(bound.min.z < FLT_EPSILON && splitCount > m_opts.maxSplits) + Box& bound = geom->bound(); + if(bound.min.z < FLT_EPSILON && geom->splitCount() > m_opts.maxSplits) { std::cerr << "Max eye splits encountered; geometry discarded\n"; return; @@ -415,27 +433,26 @@ void Renderer::push(const boost::shared_ptr<Geometry>& geom, } // If we get to here the surface should be rendered, so push it // onto the queue. - m_surfaces->push(SurfaceHolder(geom, splitCount, bound, - parentSurface.attrs)); + m_surfaces->push(geom); } // Push a grid onto the render queue void Renderer::push(const boost::shared_ptr<Grid>& grid, - const SurfaceHolder& parentSurface) + const GeomHolder& parentSurface) { // For now, just rasterize it directly. switch(grid->type()) { case GridType_QuadSimple: rasterizeSimple(static_cast<QuadGridSimple&>(*grid), - *parentSurface.attrs); + parentSurface.attrs()); break; case GridType_Quad: - if(parentSurface.attrs->surfaceShader) - parentSurface.attrs->surfaceShader->shade(*grid); + if(parentSurface.attrs().surfaceShader) + parentSurface.attrs().surfaceShader->shade(*grid); rasterize<QuadGrid, MicroQuadSampler>( - static_cast<QuadGrid&>(*grid), *parentSurface.attrs); + static_cast<QuadGrid&>(*grid), parentSurface.attrs()); break; } } @@ -487,11 +504,8 @@ void Renderer::add(const boost::shared_ptr<Geometry>& geom, Attributes& attrs) { // TODO: Transform to camera space? - // - // We need a dummy holder here for the "parent" surface; it's only - // really required to pass the attributes and split count on. - SurfaceHolder fakeParent(boost::shared_ptr<Geometry>(), -1, Box(), &attrs); - push(geom, fakeParent); + GeomHolderPtr holder(new GeomHolder(geom, &attrs)); + push(holder); } // Render all surfaces and save resulting image. @@ -511,10 +525,10 @@ void Renderer::render() while(!m_surfaces->empty()) { - SurfaceHolder s = m_surfaces->top(); + GeomHolderPtr s = m_surfaces->top(); m_surfaces->pop(); - tessContext.setParent(s); - s.geom->tessellate(splitTrans, tessContext); + tessContext.setParent(*s); + s->geom().tessellate(splitTrans, tessContext); } saveImages("test"); } diff --git a/prototypes/newcore/renderer.h b/prototypes/newcore/renderer.h index 71668a7..9993c15 100644 --- a/prototypes/newcore/renderer.h +++ b/prototypes/newcore/renderer.h @@ -24,6 +24,7 @@ #include <queue> #include <vector> +#include <boost/intrusive_ptr.hpp> #include <boost/shared_ptr.hpp> #include <boost/scoped_array.hpp> #include <boost/scoped_ptr.hpp> @@ -102,9 +103,10 @@ class Renderer // push() surfaces and grids into the renderer. friend class TessellationContextImpl; - struct SurfaceHolder; + class GeomHolder; + typedef boost::intrusive_ptr<GeomHolder> GeomHolderPtr; class SurfaceOrder; - typedef std::priority_queue<SurfaceHolder, std::vector<SurfaceHolder>, + typedef std::priority_queue<GeomHolder, std::vector<GeomHolderPtr>, SurfaceOrder> SurfaceQueue; Options m_opts; ///< Render options @@ -117,10 +119,9 @@ class Renderer void saveImages(const std::string& baseFileName); - void push(const boost::shared_ptr<Geometry>& geom, - const SurfaceHolder& parentSurface); + void push(const GeomHolderPtr& geom); void push(const boost::shared_ptr<Grid>& grid, - const SurfaceHolder& parentSurface); + const GeomHolder& parentSurface); template<typename GridT, typename PolySamplerT> void rasterize(GridT& grid, const Attributes& attrs); diff --git a/prototypes/newcore/simple.h b/prototypes/newcore/simple.h index 7d2fd77..0030d8f 100644 --- a/prototypes/newcore/simple.h +++ b/prototypes/newcore/simple.h @@ -85,7 +85,7 @@ class PatchSimple : public Geometry friend class SurfaceSplitter<PatchSimple>; friend class SurfaceDicer<PatchSimple>; - void dice(int uRes, int vRes, TessellationContext& tessCtx) + void dice(int uRes, int vRes, TessellationContext& tessCtx) const { boost::shared_ptr<QuadGridSimple> grid(new QuadGridSimple(uRes, vRes)); @@ -102,7 +102,7 @@ class PatchSimple : public Geometry tessCtx.push(grid); } - void split(bool splitInU, TessellationContext& tessCtx) + void split(bool splitInU, TessellationContext& tessCtx) const { if(splitInU) { diff --git a/prototypes/newcore/surfaces.h b/prototypes/newcore/surfaces.h index 23d0556..4891eab 100644 --- a/prototypes/newcore/surfaces.h +++ b/prototypes/newcore/surfaces.h @@ -103,7 +103,7 @@ class Patch : public Geometry tessCtx.push(grid); } - void split(bool splitInU, TessellationContext& tessCtx) + void split(bool splitInU, TessellationContext& tessCtx) const { // Split if(splitInU) diff --git a/prototypes/newcore/util.h b/prototypes/newcore/util.h index 7152bdd..90efc8c 100644 --- a/prototypes/newcore/util.h +++ b/prototypes/newcore/util.h @@ -31,6 +31,7 @@ #include <boost/utility/enable_if.hpp> #include <boost/type_traits/arithmetic_traits.hpp> +#include <boost/type_traits/is_base_of.hpp> // The distinction here is only due to the layout of the // win32libs copy of OpenEXR. @@ -49,13 +50,6 @@ #endif -template<typename T> -inline T* get(std::vector<T>& v) { return v.empty() ? 0 : v[0]; } - -template<typename T> -inline const T* get(const std::vector<T>& v) { return v.empty() ? 0 : v[0]; } - - typedef Imath::V3f Vec3; typedef Imath::V2f Vec2; typedef Imath::M44f Mat4; @@ -253,8 +247,45 @@ inline Imath::V2i ifloor(const Imath::Vec2<T>& v) #define ALLOCA(type, len) static_cast<type*>(alloca(len*sizeof(type))) #define FALLOCA(len) ALLOCA(float, len) +template<typename T, size_t sz> int array_len(T (&a)[sz]) { return sz; } + + +/// Reference counting machinary. + inline void nullDeleter(const void*) { } -template<typename T, size_t sz> int array_len(T (&a)[sz]) { return sz; } +/// Reference counted base for use with boost::intrusive_ptr. +/// +/// This is a non-virtual implementation for maximum efficiency. +class RefCounted +{ + private: + mutable int m_refCount; + public: + int refCount() const { return m_refCount; } + int incRef() const { return ++m_refCount; } + int decRef() const { return --m_refCount; } +}; + + +/// Add a reference to a RefCounted object. +inline void intrusive_ptr_add_ref(RefCounted* p) +{ + p->incRef(); +} + +/// Release a reference to a RefCounted object. +/// +/// Note that this function *must* be a template, because RefCounted does not +/// have a virtual destructor. (Therefore, if we just took p as type +/// RefCounted*, the wrong destructor would get called!) +template<typename T> +inline typename boost::enable_if<boost::is_base_of<RefCounted, T> >::type +intrusive_ptr_release(T* p) +{ + if(p->decRef() == 0) + delete p; +} + #endif // UTIL_H_INCLUDED ----------------------------------------------------------------------- Summary of changes: prototypes/newcore/attributes.h | 2 +- prototypes/newcore/filters.h | 6 +- prototypes/newcore/geometry.h | 18 +++-- prototypes/newcore/grid.h | 8 ++- prototypes/newcore/gridstorage.h | 9 ++- prototypes/newcore/gridstorage_test.cpp | 12 ++-- prototypes/newcore/primvar.h | 9 ++- prototypes/newcore/primvar_test.cpp | 2 +- prototypes/newcore/renderer.cpp | 117 +++++++++++++++++-------------- prototypes/newcore/renderer.h | 17 +++-- prototypes/newcore/scenes/default.cpp | 2 +- prototypes/newcore/scenes/tenpatch.cpp | 6 +- prototypes/newcore/shader.cpp | 10 ++-- prototypes/newcore/shader.h | 8 ++- prototypes/newcore/simple.h | 18 +++--- prototypes/newcore/surfaces.h | 28 ++++---- prototypes/newcore/util.h | 54 ++++++++++++-- 17 files changed, 192 insertions(+), 134 deletions(-) hooks/post-receive -- Aqsis Renderer |