Cycles: code refactoring to add generic lookup table memory.

This commit is contained in:
Brecht Van Lommel
2013-04-01 20:26:43 +00:00
parent 8588fec935
commit 40b05d364e
16 changed files with 274 additions and 209 deletions

View 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
)

View File

@@ -22,9 +22,12 @@
#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_)

View 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_);

View File

@@ -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

View File

@@ -20,19 +20,19 @@
#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 "particles.h"
#include "curves.h"
#include "scene.h"
#include "svm.h"
#include "osl.h"
#include "particles.h"
#include "scene.h"
#include "shader.h"
#include "svm.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);

View 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;

View File

@@ -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

View File

@@ -16,8 +16,10 @@
* 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;
bool need_update;
struct Table {
size_t offset;
size_t size;
};
Filter();
~Filter();
bool need_update;
list<Table> lookup_tables;
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__ */