Cycles: code refactoring to add generic lookup table memory.
This commit is contained in:
@@ -19,7 +19,6 @@
|
|||||||
#include "background.h"
|
#include "background.h"
|
||||||
#include "camera.h"
|
#include "camera.h"
|
||||||
#include "film.h"
|
#include "film.h"
|
||||||
#include "../render/filter.h"
|
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
#include "integrator.h"
|
#include "integrator.h"
|
||||||
#include "light.h"
|
#include "light.h"
|
||||||
@@ -213,18 +212,11 @@ void BlenderSync::sync_film()
|
|||||||
Film prevfilm = *film;
|
Film prevfilm = *film;
|
||||||
|
|
||||||
film->exposure = get_float(cscene, "film_exposure");
|
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))
|
if(film->modified(prevfilm))
|
||||||
film->tag_update(scene);
|
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 */
|
/* Render Layer */
|
||||||
|
@@ -216,6 +216,14 @@ public:
|
|||||||
return mem;
|
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)
|
void reference(T *ptr, size_t width, size_t height = 0)
|
||||||
{
|
{
|
||||||
data.clear();
|
data.clear();
|
||||||
|
@@ -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)
|
float lens_u, float lens_v, float time, Ray *ray)
|
||||||
{
|
{
|
||||||
/* pixel filter */
|
/* pixel filter */
|
||||||
float raster_x = x + kernel_tex_interp(__filter_table, filter_u, FILTER_TABLE_SIZE);
|
int filter_table_offset = kernel_data.film.filter_table_offset;
|
||||||
float raster_y = y + kernel_tex_interp(__filter_table, filter_v, FILTER_TABLE_SIZE);
|
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__
|
#ifdef __CAMERA_MOTION__
|
||||||
/* motion blur */
|
/* motion blur */
|
||||||
|
@@ -57,7 +57,7 @@ template<typename T> struct texture {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
float interp(float x, int size)
|
float lookup(float x, int offset, int size)
|
||||||
{
|
{
|
||||||
kernel_assert(size == width);
|
kernel_assert(size == width);
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ template<typename T> struct texture {
|
|||||||
int nindex = min(index+1, width-1);
|
int nindex = min(index+1, width-1);
|
||||||
float t = x - index;
|
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;
|
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(tex, index) (kg->tex.fetch(index))
|
||||||
#define kernel_tex_fetch_m128(tex, index) (kg->tex.fetch_m128(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_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_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)
|
#define kernel_data (kg->__data)
|
||||||
|
@@ -58,7 +58,7 @@ typedef texture<uchar4, 2, cudaReadModeNormalizedFloat> texture_image_uchar4;
|
|||||||
/* Macros to handle different memory storage on different devices */
|
/* Macros to handle different memory storage on different devices */
|
||||||
|
|
||||||
#define kernel_tex_fetch(t, index) tex1Dfetch(t, index)
|
#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_tex_image_interp(t, x, y) tex2D(t, x, y)
|
||||||
|
|
||||||
#define kernel_data __data
|
#define kernel_data __data
|
||||||
|
@@ -46,7 +46,7 @@
|
|||||||
#define kernel_assert(cond)
|
#define kernel_assert(cond)
|
||||||
|
|
||||||
/* manual implementation of interpolated 1D lookup */
|
/* 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;
|
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);
|
int nindex = min(index+1, width-1);
|
||||||
float t = x - index;
|
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 */
|
/* 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 */
|
/* data lookup defines */
|
||||||
#define kernel_data (*kg->data)
|
#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 kernel_tex_fetch(t, index) kg->t[index]
|
||||||
|
|
||||||
/* define NULL */
|
/* define NULL */
|
||||||
|
@@ -66,8 +66,8 @@ KERNEL_TEX(uint4, texture_uint4, __svm_nodes)
|
|||||||
KERNEL_TEX(uint, texture_uint, __shader_flag)
|
KERNEL_TEX(uint, texture_uint, __shader_flag)
|
||||||
KERNEL_TEX(uint, texture_uint, __object_flag)
|
KERNEL_TEX(uint, texture_uint, __object_flag)
|
||||||
|
|
||||||
/* camera/film */
|
/* lookup tables */
|
||||||
KERNEL_TEX(float, texture_float, __filter_table)
|
KERNEL_TEX(float, texture_float, __lookup_table)
|
||||||
|
|
||||||
/* sobol */
|
/* sobol */
|
||||||
KERNEL_TEX(uint, texture_uint, __sobol_directions)
|
KERNEL_TEX(uint, texture_uint, __sobol_directions)
|
||||||
|
@@ -611,8 +611,9 @@ typedef struct KernelFilm {
|
|||||||
|
|
||||||
int pass_shadow;
|
int pass_shadow;
|
||||||
float pass_shadow_scale;
|
float pass_shadow_scale;
|
||||||
int pass_pad1;
|
|
||||||
int pass_pad2;
|
int filter_table_offset;
|
||||||
|
int filter_pad;
|
||||||
} KernelFilm;
|
} KernelFilm;
|
||||||
|
|
||||||
typedef struct KernelBackground {
|
typedef struct KernelBackground {
|
||||||
|
@@ -20,7 +20,6 @@ set(SRC
|
|||||||
camera.cpp
|
camera.cpp
|
||||||
film.cpp
|
film.cpp
|
||||||
# film_response.cpp (code unused)
|
# film_response.cpp (code unused)
|
||||||
filter.cpp
|
|
||||||
graph.cpp
|
graph.cpp
|
||||||
image.cpp
|
image.cpp
|
||||||
integrator.cpp
|
integrator.cpp
|
||||||
@@ -37,6 +36,7 @@ set(SRC
|
|||||||
shader.cpp
|
shader.cpp
|
||||||
sobol.cpp
|
sobol.cpp
|
||||||
svm.cpp
|
svm.cpp
|
||||||
|
tables.cpp
|
||||||
tile.cpp
|
tile.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -47,7 +47,6 @@ set(SRC_HEADERS
|
|||||||
camera.h
|
camera.h
|
||||||
film.h
|
film.h
|
||||||
# film_response.h (code unused)
|
# film_response.h (code unused)
|
||||||
filter.h
|
|
||||||
graph.h
|
graph.h
|
||||||
image.h
|
image.h
|
||||||
integrator.h
|
integrator.h
|
||||||
@@ -63,6 +62,7 @@ set(SRC_HEADERS
|
|||||||
shader.h
|
shader.h
|
||||||
sobol.h
|
sobol.h
|
||||||
svm.h
|
svm.h
|
||||||
|
tables.h
|
||||||
tile.h
|
tile.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -22,9 +22,12 @@
|
|||||||
#include "integrator.h"
|
#include "integrator.h"
|
||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
#include "scene.h"
|
#include "scene.h"
|
||||||
|
#include "tables.h"
|
||||||
|
|
||||||
#include "util_algorithm.h"
|
#include "util_algorithm.h"
|
||||||
|
#include "util_debug.h"
|
||||||
#include "util_foreach.h"
|
#include "util_foreach.h"
|
||||||
|
#include "util_math.h"
|
||||||
|
|
||||||
CCL_NAMESPACE_BEGIN
|
CCL_NAMESPACE_BEGIN
|
||||||
|
|
||||||
@@ -171,12 +174,84 @@ bool Pass::contains(const vector<Pass>& passes, PassType type)
|
|||||||
return false;
|
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::Film()
|
Film::Film()
|
||||||
{
|
{
|
||||||
exposure = 0.8f;
|
exposure = 0.8f;
|
||||||
Pass::add(PASS_COMBINED, passes);
|
Pass::add(PASS_COMBINED, passes);
|
||||||
|
|
||||||
|
filter_type = FILTER_BOX;
|
||||||
|
filter_width = 1.0f;
|
||||||
|
filter_table_offset = -1;
|
||||||
|
|
||||||
need_update = true;
|
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)
|
if(!need_update)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
device_free(device, dscene, scene);
|
||||||
|
|
||||||
KernelFilm *kfilm = &dscene->data.film;
|
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);
|
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;
|
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)
|
bool Film::modified(const Film& film)
|
||||||
{
|
{
|
||||||
return !(exposure == film.exposure
|
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_)
|
void Film::tag_passes_update(Scene *scene, const vector<Pass>& passes_)
|
||||||
|
@@ -30,6 +30,11 @@ class Device;
|
|||||||
class DeviceScene;
|
class DeviceScene;
|
||||||
class Scene;
|
class Scene;
|
||||||
|
|
||||||
|
typedef enum FilterType {
|
||||||
|
FILTER_BOX,
|
||||||
|
FILTER_GAUSSIAN
|
||||||
|
} FilterType;
|
||||||
|
|
||||||
class Pass {
|
class Pass {
|
||||||
public:
|
public:
|
||||||
PassType type;
|
PassType type;
|
||||||
@@ -47,13 +52,18 @@ class Film {
|
|||||||
public:
|
public:
|
||||||
float exposure;
|
float exposure;
|
||||||
vector<Pass> passes;
|
vector<Pass> passes;
|
||||||
|
|
||||||
|
FilterType filter_type;
|
||||||
|
float filter_width;
|
||||||
|
size_t filter_table_offset;
|
||||||
|
|
||||||
bool need_update;
|
bool need_update;
|
||||||
|
|
||||||
Film();
|
Film();
|
||||||
~Film();
|
~Film();
|
||||||
|
|
||||||
void device_update(Device *device, DeviceScene *dscene);
|
void device_update(Device *device, DeviceScene *dscene, Scene *scene);
|
||||||
void device_free(Device *device, DeviceScene *dscene);
|
void device_free(Device *device, DeviceScene *dscene, Scene *scene);
|
||||||
|
|
||||||
bool modified(const Film& film);
|
bool modified(const Film& film);
|
||||||
void tag_passes_update(Scene *scene, const vector<Pass>& passes_);
|
void tag_passes_update(Scene *scene, const vector<Pass>& passes_);
|
||||||
|
@@ -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
|
|
||||||
|
|
@@ -20,19 +20,19 @@
|
|||||||
|
|
||||||
#include "background.h"
|
#include "background.h"
|
||||||
#include "camera.h"
|
#include "camera.h"
|
||||||
|
#include "curves.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "film.h"
|
#include "film.h"
|
||||||
#include "filter.h"
|
|
||||||
#include "integrator.h"
|
#include "integrator.h"
|
||||||
#include "light.h"
|
#include "light.h"
|
||||||
#include "shader.h"
|
|
||||||
#include "mesh.h"
|
#include "mesh.h"
|
||||||
#include "object.h"
|
#include "object.h"
|
||||||
#include "particles.h"
|
|
||||||
#include "curves.h"
|
|
||||||
#include "scene.h"
|
|
||||||
#include "svm.h"
|
|
||||||
#include "osl.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_foreach.h"
|
||||||
#include "util_progress.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));
|
memset(&dscene.data, 0, sizeof(dscene.data));
|
||||||
|
|
||||||
camera = new Camera();
|
camera = new Camera();
|
||||||
filter = new Filter();
|
lookup_tables = new LookupTables();
|
||||||
film = new Film();
|
film = new Film();
|
||||||
background = new Background();
|
background = new Background();
|
||||||
light_manager = new LightManager();
|
light_manager = new LightManager();
|
||||||
@@ -93,8 +93,7 @@ void Scene::free_memory(bool final)
|
|||||||
|
|
||||||
if(device) {
|
if(device) {
|
||||||
camera->device_free(device, &dscene);
|
camera->device_free(device, &dscene);
|
||||||
filter->device_free(device, &dscene);
|
film->device_free(device, &dscene, this);
|
||||||
film->device_free(device, &dscene);
|
|
||||||
background->device_free(device, &dscene);
|
background->device_free(device, &dscene);
|
||||||
integrator->device_free(device, &dscene);
|
integrator->device_free(device, &dscene);
|
||||||
|
|
||||||
@@ -108,10 +107,12 @@ void Scene::free_memory(bool final)
|
|||||||
|
|
||||||
if(!params.persistent_data || final)
|
if(!params.persistent_data || final)
|
||||||
image_manager->device_free(device, &dscene);
|
image_manager->device_free(device, &dscene);
|
||||||
|
|
||||||
|
lookup_tables->device_free(device, &dscene);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(final) {
|
if(final) {
|
||||||
delete filter;
|
delete lookup_tables;
|
||||||
delete camera;
|
delete camera;
|
||||||
delete film;
|
delete film;
|
||||||
delete background;
|
delete background;
|
||||||
@@ -186,15 +187,11 @@ void Scene::device_update(Device *device_, Progress& progress)
|
|||||||
progress.set_status("Updating Particle Systems");
|
progress.set_status("Updating Particle Systems");
|
||||||
particle_system_manager->device_update(device, &dscene, this, progress);
|
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;
|
if(progress.get_cancel()) return;
|
||||||
|
|
||||||
progress.set_status("Updating Film");
|
progress.set_status("Updating Film");
|
||||||
film->device_update(device, &dscene);
|
film->device_update(device, &dscene, this);
|
||||||
|
|
||||||
if(progress.get_cancel()) return;
|
if(progress.get_cancel()) return;
|
||||||
|
|
||||||
@@ -203,6 +200,11 @@ void Scene::device_update(Device *device_, Progress& progress)
|
|||||||
|
|
||||||
if(progress.get_cancel()) return;
|
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");
|
progress.set_status("Updating Device", "Writing constant memory");
|
||||||
device->const_copy_to("__data", &dscene.data, sizeof(dscene.data));
|
device->const_copy_to("__data", &dscene.data, sizeof(dscene.data));
|
||||||
}
|
}
|
||||||
@@ -247,7 +249,7 @@ bool Scene::need_reset()
|
|||||||
|| object_manager->need_update
|
|| object_manager->need_update
|
||||||
|| mesh_manager->need_update
|
|| mesh_manager->need_update
|
||||||
|| light_manager->need_update
|
|| light_manager->need_update
|
||||||
|| filter->need_update
|
|| lookup_tables->need_update
|
||||||
|| integrator->need_update
|
|| integrator->need_update
|
||||||
|| shader_manager->need_update
|
|| shader_manager->need_update
|
||||||
|| particle_system_manager->need_update
|
|| particle_system_manager->need_update
|
||||||
@@ -261,7 +263,6 @@ void Scene::reset()
|
|||||||
|
|
||||||
/* ensure all objects are updated */
|
/* ensure all objects are updated */
|
||||||
camera->tag_update();
|
camera->tag_update();
|
||||||
filter->tag_update(this);
|
|
||||||
film->tag_update(this);
|
film->tag_update(this);
|
||||||
background->tag_update(this);
|
background->tag_update(this);
|
||||||
integrator->tag_update(this);
|
integrator->tag_update(this);
|
||||||
|
@@ -39,10 +39,10 @@ class Camera;
|
|||||||
class Device;
|
class Device;
|
||||||
class DeviceInfo;
|
class DeviceInfo;
|
||||||
class Film;
|
class Film;
|
||||||
class Filter;
|
|
||||||
class Integrator;
|
class Integrator;
|
||||||
class Light;
|
class Light;
|
||||||
class LightManager;
|
class LightManager;
|
||||||
|
class LookupTables;
|
||||||
class Mesh;
|
class Mesh;
|
||||||
class MeshManager;
|
class MeshManager;
|
||||||
class Object;
|
class Object;
|
||||||
@@ -99,8 +99,8 @@ public:
|
|||||||
device_vector<uint> shader_flag;
|
device_vector<uint> shader_flag;
|
||||||
device_vector<uint> object_flag;
|
device_vector<uint> object_flag;
|
||||||
|
|
||||||
/* filter */
|
/* lookup tables */
|
||||||
device_vector<float> filter_table;
|
device_vector<float> lookup_table;
|
||||||
|
|
||||||
/* integrator */
|
/* integrator */
|
||||||
device_vector<uint> sobol_directions;
|
device_vector<uint> sobol_directions;
|
||||||
@@ -155,7 +155,7 @@ class Scene {
|
|||||||
public:
|
public:
|
||||||
/* data */
|
/* data */
|
||||||
Camera *camera;
|
Camera *camera;
|
||||||
Filter *filter;
|
LookupTables *lookup_tables;
|
||||||
Film *film;
|
Film *film;
|
||||||
Background *background;
|
Background *background;
|
||||||
Integrator *integrator;
|
Integrator *integrator;
|
||||||
|
106
intern/cycles/render/tables.cpp
Normal file
106
intern/cycles/render/tables.cpp
Normal 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
|
||||||
|
|
@@ -16,8 +16,10 @@
|
|||||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __FILTER_H__
|
#ifndef __TABLES_H__
|
||||||
#define __FILTER_H__
|
#define __TABLES_H__
|
||||||
|
|
||||||
|
#include <util_list.h>
|
||||||
|
|
||||||
CCL_NAMESPACE_BEGIN
|
CCL_NAMESPACE_BEGIN
|
||||||
|
|
||||||
@@ -25,29 +27,29 @@ class Device;
|
|||||||
class DeviceScene;
|
class DeviceScene;
|
||||||
class Scene;
|
class Scene;
|
||||||
|
|
||||||
typedef enum FilterType {
|
enum { TABLE_CHUNK_SIZE = 256 };
|
||||||
FILTER_BOX,
|
|
||||||
FILTER_GAUSSIAN
|
|
||||||
} FilterType;
|
|
||||||
|
|
||||||
class Filter {
|
class LookupTables {
|
||||||
public:
|
public:
|
||||||
/* pixel filter */
|
struct Table {
|
||||||
FilterType filter_type;
|
size_t offset;
|
||||||
float filter_width;
|
size_t size;
|
||||||
bool need_update;
|
};
|
||||||
|
|
||||||
Filter();
|
bool need_update;
|
||||||
~Filter();
|
list<Table> lookup_tables;
|
||||||
|
|
||||||
|
LookupTables();
|
||||||
|
~LookupTables();
|
||||||
|
|
||||||
void device_update(Device *device, DeviceScene *dscene);
|
void device_update(Device *device, DeviceScene *dscene);
|
||||||
void device_free(Device *device, DeviceScene *dscene);
|
void device_free(Device *device, DeviceScene *dscene);
|
||||||
|
|
||||||
bool modified(const Filter& filter);
|
size_t add_table(DeviceScene *dscene, vector<float>& data);
|
||||||
void tag_update(Scene *scene);
|
void remove_table(size_t offset);
|
||||||
};
|
};
|
||||||
|
|
||||||
CCL_NAMESPACE_END
|
CCL_NAMESPACE_END
|
||||||
|
|
||||||
#endif /* __FILTER_H__ */
|
#endif /* __TABLES_H__ */
|
||||||
|
|
Reference in New Issue
Block a user