Cycles: code refactoring to add generic lookup table memory.
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Mon, 1 Apr 2013 20:26:43 +0000 (20:26 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Mon, 1 Apr 2013 20:26:43 +0000 (20:26 +0000)
16 files changed:
intern/cycles/blender/blender_sync.cpp
intern/cycles/device/device_memory.h
intern/cycles/kernel/kernel_camera.h
intern/cycles/kernel/kernel_compat_cpu.h
intern/cycles/kernel/kernel_compat_cuda.h
intern/cycles/kernel/kernel_compat_opencl.h
intern/cycles/kernel/kernel_textures.h
intern/cycles/kernel/kernel_types.h
intern/cycles/render/CMakeLists.txt
intern/cycles/render/film.cpp
intern/cycles/render/film.h
intern/cycles/render/filter.cpp [deleted file]
intern/cycles/render/scene.cpp
intern/cycles/render/scene.h
intern/cycles/render/tables.cpp [new file with mode: 0644]
intern/cycles/render/tables.h [moved from intern/cycles/render/filter.h with 73% similarity]

index f6ff78ab2ace8c0f6bbc2151cfc0f1f342c38ed6..66401d80a2e88af10e663d0947cf8e9ca742a863 100644 (file)
@@ -19,7 +19,6 @@
 #include "background.h"
 #include "camera.h"
 #include "film.h"
-#include "../render/filter.h"
 #include "graph.h"
 #include "integrator.h"
 #include "light.h"
@@ -213,18 +212,11 @@ void BlenderSync::sync_film()
        Film prevfilm = *film;
 
        film->exposure = get_float(cscene, "film_exposure");
+       film->filter_type = (FilterType)RNA_enum_get(&cscene, "filter_type");
+       film->filter_width = (film->filter_type == FILTER_BOX)? 1.0f: get_float(cscene, "filter_width");
 
        if(film->modified(prevfilm))
                film->tag_update(scene);
-
-       Filter *filter = scene->filter;
-       Filter prevfilter = *filter;
-
-       filter->filter_type = (FilterType)RNA_enum_get(&cscene, "filter_type");
-       filter->filter_width = (filter->filter_type == FILTER_BOX)? 1.0f: get_float(cscene, "filter_width");
-
-       if(filter->modified(prevfilter))
-               filter->tag_update(scene);
 }
 
 /* Render Layer */
index 3223ca91b9e3de1fe5f9d1b76af1ed647d455366..fd0bed33396ec7a15bf9c4ab9c0dfdfe64f05eab 100644 (file)
@@ -216,6 +216,14 @@ public:
                return mem;
        }
 
+       void copy_at(T *ptr, size_t offset, size_t size)
+       {
+               if(size > 0) {
+                       size_t mem_size = size*data_elements*datatype_size(data_type);
+                       memcpy(&data[0] + offset, ptr, mem_size);
+               }
+       }
+
        void reference(T *ptr, size_t width, size_t height = 0)
        {
                data.clear();
index 02f64cd649a2342a5fda9436a62bdbe9a0144c93..1d081b5468177448de0055ba2a017f997d9f0b1b 100644 (file)
@@ -224,8 +224,9 @@ __device void camera_sample(KernelGlobals *kg, int x, int y, float filter_u, flo
        float lens_u, float lens_v, float time, Ray *ray)
 {
        /* pixel filter */
-       float raster_x = x + kernel_tex_interp(__filter_table, filter_u, FILTER_TABLE_SIZE);
-       float raster_y = y + kernel_tex_interp(__filter_table, filter_v, FILTER_TABLE_SIZE);
+       int filter_table_offset = kernel_data.film.filter_table_offset;
+       float raster_x = x + kernel_tex_lookup(__lookup_table, filter_u, filter_table_offset, FILTER_TABLE_SIZE);
+       float raster_y = y + kernel_tex_lookup(__lookup_table, filter_v, filter_table_offset, FILTER_TABLE_SIZE);
 
 #ifdef __CAMERA_MOTION__
        /* motion blur */
index 01bb78e8e1c52a0a563d8da30e1e10ba81dc84f3..b7df7f86bf62c78ee6096eabd182f09f8f8bde1f 100644 (file)
@@ -57,7 +57,7 @@ template<typename T> struct texture  {
        }
 #endif
 
-       float interp(float x, int size)
+       float lookup(float x, int offset, int size)
        {
                kernel_assert(size == width);
 
@@ -67,7 +67,7 @@ template<typename T> struct texture  {
                int nindex = min(index+1, width-1);
                float t = x - index;
 
-               return (1.0f - t)*data[index] + t*data[nindex];
+               return (1.0f - t)*data[index + offset] + t*data[nindex + offset];
        }
 
        T *data;
@@ -157,7 +157,7 @@ typedef texture_image<uchar4> texture_image_uchar4;
 #define kernel_tex_fetch(tex, index) (kg->tex.fetch(index))
 #define kernel_tex_fetch_m128(tex, index) (kg->tex.fetch_m128(index))
 #define kernel_tex_fetch_m128i(tex, index) (kg->tex.fetch_m128i(index))
-#define kernel_tex_interp(tex, t, size) (kg->tex.interp(t, size))
+#define kernel_tex_lookup(tex, t, offset, size) (kg->tex.lookup(t, offset, size))
 #define kernel_tex_image_interp(tex, x, y) ((tex < MAX_FLOAT_IMAGES) ? kg->texture_float_images[tex].interp(x, y) : kg->texture_byte_images[tex - MAX_FLOAT_IMAGES].interp(x, y))
 
 #define kernel_data (kg->__data)
index 9fd065c3cda0679a72604ca841880a5f30a1e975..fdee59e225e04f7239c408d5078704802ddd5d5b 100644 (file)
@@ -58,7 +58,7 @@ typedef texture<uchar4, 2, cudaReadModeNormalizedFloat> texture_image_uchar4;
 /* Macros to handle different memory storage on different devices */
 
 #define kernel_tex_fetch(t, index) tex1Dfetch(t, index)
-#define kernel_tex_interp(t, x, size) tex1D(t, x)
+#define kernel_tex_lookup(t, x, offset, size) tex1D(t, x) // XXX broken!
 #define kernel_tex_image_interp(t, x, y) tex2D(t, x, y)
 
 #define kernel_data __data
index abb2f094f5cc23a5cc1cd6c396a12c5015d74257..dcbaf8fdbd25b7204319f4712d7035a6a8d86cf5 100644 (file)
@@ -46,7 +46,7 @@
 #define kernel_assert(cond)
 
 /* manual implementation of interpolated 1D lookup */
-__device float kernel_tex_interp_(__global float *data, int width, float x)
+__device float kernel_tex_lookup_(__global float *data, int offset, int width, float x)
 {
        x = clamp(x, 0.0f, 1.0f)*width;
 
@@ -54,7 +54,7 @@ __device float kernel_tex_interp_(__global float *data, int width, float x)
        int nindex = min(index+1, width-1);
        float t = x - index;
 
-       return (1.0f - t)*data[index] + t*data[nindex];
+       return (1.0f - t)*data[index + offset] + t*data[nindex + offset];
 }
 
 /* make_type definitions with opencl style element initializers */
@@ -114,7 +114,7 @@ __device float kernel_tex_interp_(__global float *data, int width, float x)
 
 /* data lookup defines */
 #define kernel_data (*kg->data)
-#define kernel_tex_interp(t, x, size) kernel_tex_interp_(kg->t, size, x)
+#define kernel_tex_lookup(t, x, offset, size) kernel_tex_lookup_(kg->t, offset, size, x)
 #define kernel_tex_fetch(t, index) kg->t[index]
 
 /* define NULL */
index e27de95e7ab59d341833f4f0f80ee0a8c630d704..55c6e15ad04b20d0dc9631037c9b62c692c6522d 100644 (file)
@@ -66,8 +66,8 @@ KERNEL_TEX(uint4, texture_uint4, __svm_nodes)
 KERNEL_TEX(uint, texture_uint, __shader_flag)
 KERNEL_TEX(uint, texture_uint, __object_flag)
 
-/* camera/film */
-KERNEL_TEX(float, texture_float, __filter_table)
+/* lookup tables */
+KERNEL_TEX(float, texture_float, __lookup_table)
 
 /* sobol */
 KERNEL_TEX(uint, texture_uint, __sobol_directions)
index ddbda9240fb8cbb069a4c27d3fc453f06989c999..f6b8a1b8b826775e5817f025dd142c426dea9f40 100644 (file)
@@ -611,8 +611,9 @@ typedef struct KernelFilm {
 
        int pass_shadow;
        float pass_shadow_scale;
-       int pass_pad1;
-       int pass_pad2;
+
+       int filter_table_offset;
+       int filter_pad;
 } KernelFilm;
 
 typedef struct KernelBackground {
index d67a686d1e89a7845a377156e5c337ebe4feac29..0f45f63d78a420ff794b7805181950f1f21fa587 100644 (file)
@@ -20,7 +20,6 @@ set(SRC
        camera.cpp
        film.cpp
        # film_response.cpp (code unused)
-       filter.cpp
        graph.cpp
        image.cpp
        integrator.cpp
@@ -37,6 +36,7 @@ set(SRC
        shader.cpp
        sobol.cpp
        svm.cpp
+       tables.cpp
        tile.cpp
 )
 
@@ -47,7 +47,6 @@ set(SRC_HEADERS
        camera.h
        film.h
        # film_response.h (code unused)
-       filter.h
        graph.h
        image.h
        integrator.h
@@ -63,6 +62,7 @@ set(SRC_HEADERS
        shader.h
        sobol.h
        svm.h
+       tables.h
        tile.h
 )
 
index fdf25ca790891d74bc5ee807489b980ab9cff9d3..7dcbfa2278c5e0c3fb31c43327f615bcfe6fe529 100644 (file)
 #include "integrator.h"
 #include "mesh.h"
 #include "scene.h"
+#include "tables.h"
 
 #include "util_algorithm.h"
+#include "util_debug.h"
 #include "util_foreach.h"
+#include "util_math.h"
 
 CCL_NAMESPACE_BEGIN
 
@@ -171,12 +174,84 @@ bool Pass::contains(const vector<Pass>& passes, PassType type)
        return false;
 }
 
+/* Pixel Filter */
+
+static float filter_func_box(float v, float width)
+{
+       return (float)1;
+}
+
+static float filter_func_gaussian(float v, float width)
+{
+       v *= (float)2/width;
+       return (float)expf((float)-2*v*v);
+}
+
+static vector<float> filter_table(FilterType type, float width)
+{
+       const int filter_table_size = FILTER_TABLE_SIZE-1;
+       vector<float> filter_table_cdf(filter_table_size+1);
+       vector<float> filter_table(filter_table_size+1);
+       float (*filter_func)(float, float) = NULL;
+       int i, half_size = filter_table_size/2;
+
+       switch(type) {
+               case FILTER_BOX:
+                       filter_func = filter_func_box;
+                       break;
+               case FILTER_GAUSSIAN:
+                       filter_func = filter_func_gaussian;
+                       break;
+               default:
+                       assert(0);
+       }
+
+       /* compute cumulative distribution function */
+       filter_table_cdf[0] = 0.0f;
+       
+       for(i = 0; i < filter_table_size; i++) {
+               float x = i*width*0.5f/(filter_table_size-1);
+               float y = filter_func(x, width);
+               filter_table_cdf[i+1] += filter_table_cdf[i] + fabsf(y);
+       }
+
+       for(i = 0; i <= filter_table_size; i++)
+               filter_table_cdf[i] /= filter_table_cdf[filter_table_size];
+       
+       /* create importance sampling table */
+       for(i = 0; i <= half_size; i++) {
+               float x = i/(float)half_size;
+               int index = upper_bound(filter_table_cdf.begin(), filter_table_cdf.end(), x) - filter_table_cdf.begin();
+               float t;
+
+               if(index < filter_table_size+1) {
+                       t = (x - filter_table_cdf[index])/(filter_table_cdf[index+1] - filter_table_cdf[index]);
+               }
+               else {
+                       t = 0.0f;
+                       index = filter_table_size;
+               }
+
+               float y = ((index + t)/(filter_table_size))*width;
+
+               filter_table[half_size+i] = 0.5f*(1.0f + y);
+               filter_table[half_size-i] = 0.5f*(1.0f - y);
+       }
+
+       return filter_table;
+}
+
 /* Film */
 
 Film::Film()
 {
        exposure = 0.8f;
        Pass::add(PASS_COMBINED, passes);
+
+       filter_type = FILTER_BOX;
+       filter_width = 1.0f;
+       filter_table_offset = -1;
+
        need_update = true;
 }
 
@@ -184,10 +259,12 @@ Film::~Film()
 {
 }
 
-void Film::device_update(Device *device, DeviceScene *dscene)
+void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
 {
        if(!need_update)
                return;
+       
+       device_free(device, dscene, scene);
 
        KernelFilm *kfilm = &dscene->data.film;
 
@@ -284,17 +361,26 @@ void Film::device_update(Device *device, DeviceScene *dscene)
 
        kfilm->pass_stride = align_up(kfilm->pass_stride, 4);
 
+       /* update filter table */
+       vector<float> table = filter_table(filter_type, filter_width);
+       filter_table_offset = scene->lookup_tables->add_table(dscene, table);
+       kfilm->filter_table_offset = (int)filter_table_offset;
+
        need_update = false;
 }
 
-void Film::device_free(Device *device, DeviceScene *dscene)
+void Film::device_free(Device *device, DeviceScene *dscene, Scene *scene)
 {
+       if(filter_table_offset != -1)
+               scene->lookup_tables->remove_table(filter_table_offset);
 }
 
 bool Film::modified(const Film& film)
 {
        return !(exposure == film.exposure
-               && Pass::equals(passes, film.passes));
+               && Pass::equals(passes, film.passes)
+               && filter_type == film.filter_type
+               && filter_width == film.filter_width);
 }
 
 void Film::tag_passes_update(Scene *scene, const vector<Pass>& passes_)
index 52d1a8428f8795c78cc8e3082366ecc95f05dc07..bc1619c3f2dcffae8d965abb5261a7a92f4fb5c8 100644 (file)
@@ -30,6 +30,11 @@ class Device;
 class DeviceScene;
 class Scene;
 
+typedef enum FilterType {
+       FILTER_BOX,
+       FILTER_GAUSSIAN
+} FilterType;
+
 class Pass {
 public:
        PassType type;
@@ -47,13 +52,18 @@ class Film {
 public:
        float exposure;
        vector<Pass> passes;
+
+       FilterType filter_type;
+       float filter_width;
+       size_t filter_table_offset;
+
        bool need_update;
 
        Film();
        ~Film();
 
-       void device_update(Device *device, DeviceScene *dscene);
-       void device_free(Device *device, DeviceScene *dscene);
+       void device_update(Device *device, DeviceScene *dscene, Scene *scene);
+       void device_free(Device *device, DeviceScene *dscene, Scene *scene);
 
        bool modified(const Film& film);
        void tag_passes_update(Scene *scene, const vector<Pass>& passes_);
diff --git a/intern/cycles/render/filter.cpp b/intern/cycles/render/filter.cpp
deleted file mode 100644 (file)
index 0bd4fb4..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright 2011, Blender Foundation.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#include "camera.h"
-#include "device.h"
-#include "filter.h"
-#include "scene.h"
-
-#include "kernel_types.h"
-
-#include "util_algorithm.h"
-#include "util_debug.h"
-#include "util_math.h"
-
-CCL_NAMESPACE_BEGIN
-
-Filter::Filter()
-{
-       filter_type = FILTER_BOX;
-       filter_width = 1.0f;
-       need_update = true;
-}
-
-Filter::~Filter()
-{
-}
-
-static float filter_func_box(float v, float width)
-{
-       return (float)1;
-}
-
-static float filter_func_gaussian(float v, float width)
-{
-       v *= (float)2/width;
-       return (float)expf((float)-2*v*v);
-}
-
-static vector<float> filter_table(FilterType type, float width)
-{
-       const int filter_table_size = FILTER_TABLE_SIZE-1;
-       vector<float> filter_table_cdf(filter_table_size+1);
-       vector<float> filter_table(filter_table_size+1);
-       float (*filter_func)(float, float) = NULL;
-       int i, half_size = filter_table_size/2;
-
-       switch(type) {
-               case FILTER_BOX:
-                       filter_func = filter_func_box;
-                       break;
-               case FILTER_GAUSSIAN:
-                       filter_func = filter_func_gaussian;
-                       break;
-               default:
-                       assert(0);
-       }
-
-       /* compute cumulative distribution function */
-       filter_table_cdf[0] = 0.0f;
-       
-       for(i = 0; i < filter_table_size; i++) {
-               float x = i*width*0.5f/(filter_table_size-1);
-               float y = filter_func(x, width);
-               filter_table_cdf[i+1] += filter_table_cdf[i] + fabsf(y);
-       }
-
-       for(i = 0; i <= filter_table_size; i++)
-               filter_table_cdf[i] /= filter_table_cdf[filter_table_size];
-       
-       /* create importance sampling table */
-       for(i = 0; i <= half_size; i++) {
-               float x = i/(float)half_size;
-               int index = upper_bound(filter_table_cdf.begin(), filter_table_cdf.end(), x) - filter_table_cdf.begin();
-               float t;
-
-               if(index < filter_table_size+1) {
-                       t = (x - filter_table_cdf[index])/(filter_table_cdf[index+1] - filter_table_cdf[index]);
-               }
-               else {
-                       t = 0.0f;
-                       index = filter_table_size;
-               }
-
-               float y = ((index + t)/(filter_table_size))*width;
-
-               filter_table[half_size+i] = 0.5f*(1.0f + y);
-               filter_table[half_size-i] = 0.5f*(1.0f - y);
-       }
-
-       return filter_table;
-}
-
-void Filter::device_update(Device *device, DeviceScene *dscene)
-{
-       if(!need_update)
-               return;
-
-       device_free(device, dscene);
-
-       /* update __filter_table */
-       vector<float> table = filter_table(filter_type, filter_width);
-
-       dscene->filter_table.copy(&table[0], table.size());
-       device->tex_alloc("__filter_table", dscene->filter_table, true);
-
-       need_update = false;
-}
-
-void Filter::device_free(Device *device, DeviceScene *dscene)
-{
-       device->tex_free(dscene->filter_table);
-       dscene->filter_table.clear();
-}
-
-bool Filter::modified(const Filter& filter)
-{
-       return !(filter_type == filter.filter_type &&
-               filter_width == filter.filter_width);
-}
-
-void Filter::tag_update(Scene *scene)
-{
-       need_update = true;
-}
-
-CCL_NAMESPACE_END
-
index 7b82a91cae8dbbf7d048b571adc54de570016973..2b0609fdf1f5fb5884193d77d6aa85292aff2659 100644 (file)
 
 #include "background.h"
 #include "camera.h"
+#include "curves.h"
 #include "device.h"
 #include "film.h"
-#include "filter.h"
 #include "integrator.h"
 #include "light.h"
-#include "shader.h"
 #include "mesh.h"
 #include "object.h"
+#include "osl.h"
 #include "particles.h"
-#include "curves.h"
 #include "scene.h"
+#include "shader.h"
 #include "svm.h"
-#include "osl.h"
+#include "tables.h"
 
 #include "util_foreach.h"
 #include "util_progress.h"
@@ -46,7 +46,7 @@ Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_)
        memset(&dscene.data, 0, sizeof(dscene.data));
 
        camera = new Camera();
-       filter = new Filter();
+       lookup_tables = new LookupTables();
        film = new Film();
        background = new Background();
        light_manager = new LightManager();
@@ -93,8 +93,7 @@ void Scene::free_memory(bool final)
 
        if(device) {
                camera->device_free(device, &dscene);
-               filter->device_free(device, &dscene);
-               film->device_free(device, &dscene);
+               film->device_free(device, &dscene, this);
                background->device_free(device, &dscene);
                integrator->device_free(device, &dscene);
 
@@ -108,10 +107,12 @@ void Scene::free_memory(bool final)
 
                if(!params.persistent_data || final)
                        image_manager->device_free(device, &dscene);
+
+               lookup_tables->device_free(device, &dscene);
        }
 
        if(final) {
-               delete filter;
+               delete lookup_tables;
                delete camera;
                delete film;
                delete background;
@@ -186,15 +187,11 @@ void Scene::device_update(Device *device_, Progress& progress)
        progress.set_status("Updating Particle Systems");
        particle_system_manager->device_update(device, &dscene, this, progress);
 
-       if(progress.get_cancel()) return;
-
-       progress.set_status("Updating Filter");
-       filter->device_update(device, &dscene);
 
        if(progress.get_cancel()) return;
 
        progress.set_status("Updating Film");
-       film->device_update(device, &dscene);
+       film->device_update(device, &dscene, this);
 
        if(progress.get_cancel()) return;
 
@@ -203,6 +200,11 @@ void Scene::device_update(Device *device_, Progress& progress)
 
        if(progress.get_cancel()) return;
 
+       progress.set_status("Updating Lookup Tables");
+       lookup_tables->device_update(device, &dscene);
+
+       if(progress.get_cancel()) return;
+
        progress.set_status("Updating Device", "Writing constant memory");
        device->const_copy_to("__data", &dscene.data, sizeof(dscene.data));
 }
@@ -247,7 +249,7 @@ bool Scene::need_reset()
                || object_manager->need_update
                || mesh_manager->need_update
                || light_manager->need_update
-               || filter->need_update
+               || lookup_tables->need_update
                || integrator->need_update
                || shader_manager->need_update
                || particle_system_manager->need_update
@@ -261,7 +263,6 @@ void Scene::reset()
 
        /* ensure all objects are updated */
        camera->tag_update();
-       filter->tag_update(this);
        film->tag_update(this);
        background->tag_update(this);
        integrator->tag_update(this);
index fc6b538af03ca80876709c9bccece6b714400532..545a765cc22be94d9097115a1c7075374f413c6f 100644 (file)
@@ -39,10 +39,10 @@ class Camera;
 class Device;
 class DeviceInfo;
 class Film;
-class Filter;
 class Integrator;
 class Light;
 class LightManager;
+class LookupTables;
 class Mesh;
 class MeshManager;
 class Object;
@@ -99,8 +99,8 @@ public:
        device_vector<uint> shader_flag;
        device_vector<uint> object_flag;
 
-       /* filter */
-       device_vector<float> filter_table;
+       /* lookup tables */
+       device_vector<float> lookup_table;
 
        /* integrator */
        device_vector<uint> sobol_directions;
@@ -155,7 +155,7 @@ class Scene {
 public:
        /* data */
        Camera *camera;
-       Filter *filter;
+       LookupTables *lookup_tables;
        Film *film;
        Background *background;
        Integrator *integrator;
diff --git a/intern/cycles/render/tables.cpp b/intern/cycles/render/tables.cpp
new file mode 100644 (file)
index 0000000..fecdd52
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2011, Blender Foundation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include "device.h"
+#include "scene.h"
+#include "tables.h"
+
+#include "util_debug.h"
+
+CCL_NAMESPACE_BEGIN
+
+LookupTables::LookupTables()
+{
+       need_update = true;
+}
+
+LookupTables::~LookupTables()
+{
+       assert(lookup_tables.size() == 0);
+}
+
+void LookupTables::device_update(Device *device, DeviceScene *dscene)
+{
+       if(!need_update)
+               return;
+
+       device->tex_alloc("__lookup_table", dscene->lookup_table, true); // XXX interpolation
+
+       need_update = false;
+}
+
+void LookupTables::device_free(Device *device, DeviceScene *dscene)
+{
+       device->tex_free(dscene->lookup_table);
+       dscene->lookup_table.clear();
+}
+
+static size_t round_up_to_multiple(size_t size, size_t chunk)
+{
+       return ((size + chunk - 1)/chunk) * chunk;
+}
+
+size_t LookupTables::add_table(DeviceScene *dscene, vector<float>& data)
+{
+       assert(data.size() > 0);
+
+       need_update = true;
+
+       Table new_table;
+       new_table.offset = 0;
+       new_table.size = round_up_to_multiple(data.size(), TABLE_CHUNK_SIZE);
+
+       /* find space to put lookup table */
+       list<Table>::iterator table;
+
+       for(table = lookup_tables.begin(); table != lookup_tables.end(); table++) {
+               if(new_table.offset + new_table.size <= table->offset) {
+                       lookup_tables.insert(table, new_table);
+                       break;
+               }
+       }
+
+       if(table == lookup_tables.end()) {
+               /* add at the end */
+               lookup_tables.push_back(new_table);
+               dscene->lookup_table.resize(new_table.offset + new_table.size);
+       }
+
+       /* copy table data and return offset */
+       dscene->lookup_table.copy_at(&data[0], new_table.offset, data.size());
+       return new_table.offset;
+}
+
+void LookupTables::remove_table(size_t offset)
+{
+       need_update = true;
+
+       list<Table>::iterator table;
+
+       for(table = lookup_tables.begin(); table != lookup_tables.end(); table++) {
+               if(table->offset == offset) {
+                       lookup_tables.erase(table);
+                       break;
+               }
+       }
+
+       assert(table != lookup_tables.end());
+}
+
+CCL_NAMESPACE_END
+
similarity index 73%
rename from intern/cycles/render/filter.h
rename to intern/cycles/render/tables.h
index 5df7bb8fd144f523f9c65c808b9a6754207e8cb7..5fa5136ae798886fa01a32e299613853190cf73f 100644 (file)
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
-#ifndef __FILTER_H__
-#define __FILTER_H__
+#ifndef __TABLES_H__
+#define __TABLES_H__
+
+#include <util_list.h>
 
 CCL_NAMESPACE_BEGIN
 
@@ -25,29 +27,29 @@ class Device;
 class DeviceScene;
 class Scene;
 
-typedef enum FilterType {
-       FILTER_BOX,
-       FILTER_GAUSSIAN
-} FilterType;
+enum { TABLE_CHUNK_SIZE = 256 };
 
-class Filter {
+class LookupTables {
 public:
-       /* pixel filter */
-       FilterType filter_type;
-       float filter_width;
+       struct Table {
+               size_t offset;
+               size_t size;
+       };
+
        bool need_update;
+       list<Table> lookup_tables;
 
-       Filter();
-       ~Filter();
+       LookupTables();
+       ~LookupTables();
 
        void device_update(Device *device, DeviceScene *dscene);
        void device_free(Device *device, DeviceScene *dscene);
 
-       bool modified(const Filter& filter);
-       void tag_update(Scene *scene);
+       size_t add_table(DeviceScene *dscene, vector<float>& data);
+       void remove_table(size_t offset);
 };
 
 CCL_NAMESPACE_END
 
-#endif /* __FILTER_H__ */
+#endif /* __TABLES_H__ */