Cycles code internals: add CPU kernel support for 3D image textures.
This commit is contained in:
@@ -90,8 +90,8 @@ bool ImageManager::is_float_image(const string& filename, void *builtin_data, bo
|
||||
|
||||
if(builtin_data) {
|
||||
if(builtin_image_info_cb) {
|
||||
int width, height, channels;
|
||||
builtin_image_info_cb(filename, builtin_data, is_float, width, height, channels);
|
||||
int width, height, depth, channels;
|
||||
builtin_image_info_cb(filename, builtin_data, is_float, width, height, depth, channels);
|
||||
}
|
||||
|
||||
if(is_float)
|
||||
@@ -145,6 +145,13 @@ bool ImageManager::is_float_image(const string& filename, void *builtin_data, bo
|
||||
return is_float;
|
||||
}
|
||||
|
||||
static bool image_equals(ImageManager::Image *image, const string& filename, void *builtin_data, bool interpolation)
|
||||
{
|
||||
return image->filename == filename &&
|
||||
image->builtin_data == builtin_data &&
|
||||
image->interpolation == interpolation;
|
||||
}
|
||||
|
||||
int ImageManager::add_image(const string& filename, void *builtin_data, bool animated, bool& is_float, bool& is_linear, InterpolationType interpolation)
|
||||
{
|
||||
Image *img;
|
||||
@@ -156,7 +163,7 @@ int ImageManager::add_image(const string& filename, void *builtin_data, bool ani
|
||||
if(is_float) {
|
||||
/* find existing image */
|
||||
for(slot = 0; slot < float_images.size(); slot++) {
|
||||
if(float_images[slot] && float_images[slot]->filename == filename && float_images[slot]->interpolation == interpolation) {
|
||||
if(float_images[slot] && image_equals(float_images[slot], filename, builtin_data, interpolation)) {
|
||||
float_images[slot]->users++;
|
||||
return slot;
|
||||
}
|
||||
@@ -192,7 +199,7 @@ int ImageManager::add_image(const string& filename, void *builtin_data, bool ani
|
||||
}
|
||||
else {
|
||||
for(slot = 0; slot < images.size(); slot++) {
|
||||
if(images[slot] && images[slot]->filename == filename && images[slot]->interpolation == interpolation) {
|
||||
if(images[slot] && image_equals(images[slot], filename, builtin_data, interpolation)) {
|
||||
images[slot]->users++;
|
||||
return slot+tex_image_byte_start;
|
||||
}
|
||||
@@ -233,22 +240,43 @@ int ImageManager::add_image(const string& filename, void *builtin_data, bool ani
|
||||
return slot;
|
||||
}
|
||||
|
||||
void ImageManager::remove_image(int slot)
|
||||
{
|
||||
if(slot >= tex_image_byte_start) {
|
||||
slot -= tex_image_byte_start;
|
||||
|
||||
assert(images[slot] != NULL);
|
||||
|
||||
/* decrement user count */
|
||||
images[slot]->users--;
|
||||
assert(images[slot]->users >= 0);
|
||||
|
||||
/* don't remove immediately, rather do it all together later on. one of
|
||||
* the reasons for this is that on shader changes we add and remove nodes
|
||||
* that use them, but we do not want to reload the image all the time. */
|
||||
if(images[slot]->users == 0)
|
||||
need_update = true;
|
||||
}
|
||||
else {
|
||||
/* decrement user count */
|
||||
float_images[slot]->users--;
|
||||
assert(float_images[slot]->users >= 0);
|
||||
|
||||
/* don't remove immediately, rather do it all together later on. one of
|
||||
* the reasons for this is that on shader changes we add and remove nodes
|
||||
* that use them, but we do not want to reload the image all the time. */
|
||||
if(float_images[slot]->users == 0)
|
||||
need_update = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ImageManager::remove_image(const string& filename, void *builtin_data, InterpolationType interpolation)
|
||||
{
|
||||
size_t slot;
|
||||
|
||||
for(slot = 0; slot < images.size(); slot++) {
|
||||
if(images[slot] && images[slot]->filename == filename && images[slot]->interpolation == interpolation && images[slot]->builtin_data == builtin_data) {
|
||||
/* decrement user count */
|
||||
images[slot]->users--;
|
||||
assert(images[slot]->users >= 0);
|
||||
|
||||
/* don't remove immediately, rather do it all together later on. one of
|
||||
* the reasons for this is that on shader changes we add and remove nodes
|
||||
* that use them, but we do not want to reload the image all the time. */
|
||||
if(images[slot]->users == 0)
|
||||
need_update = true;
|
||||
|
||||
if(images[slot] && image_equals(images[slot], filename, builtin_data, interpolation)) {
|
||||
remove_image(slot+tex_image_byte_start);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -256,19 +284,8 @@ void ImageManager::remove_image(const string& filename, void *builtin_data, Inte
|
||||
if(slot == images.size()) {
|
||||
/* see if it's in a float texture slot */
|
||||
for(slot = 0; slot < float_images.size(); slot++) {
|
||||
if(float_images[slot] && float_images[slot]->filename == filename
|
||||
&& float_images[slot]->interpolation == interpolation
|
||||
&& float_images[slot]->builtin_data == builtin_data) {
|
||||
/* decrement user count */
|
||||
float_images[slot]->users--;
|
||||
assert(float_images[slot]->users >= 0);
|
||||
|
||||
/* don't remove immediately, rather do it all together later on. one of
|
||||
* the reasons for this is that on shader changes we add and remove nodes
|
||||
* that use them, but we do not want to reload the image all the time. */
|
||||
if(float_images[slot]->users == 0)
|
||||
need_update = true;
|
||||
|
||||
if(float_images[slot] && image_equals(float_images[slot], filename, builtin_data, interpolation)) {
|
||||
remove_image(slot);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -281,7 +298,7 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
|
||||
return false;
|
||||
|
||||
ImageInput *in = NULL;
|
||||
int width, height, components;
|
||||
int width, height, depth, components;
|
||||
|
||||
if(!img->builtin_data) {
|
||||
/* load image from file through OIIO */
|
||||
@@ -299,6 +316,7 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
|
||||
|
||||
width = spec.width;
|
||||
height = spec.height;
|
||||
depth = spec.depth;
|
||||
components = spec.nchannels;
|
||||
}
|
||||
else {
|
||||
@@ -307,7 +325,7 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
|
||||
return false;
|
||||
|
||||
bool is_float;
|
||||
builtin_image_info_cb(img->filename, img->builtin_data, is_float, width, height, components);
|
||||
builtin_image_info_cb(img->filename, img->builtin_data, is_float, width, height, depth, components);
|
||||
}
|
||||
|
||||
/* we only handle certain number of components */
|
||||
@@ -321,15 +339,21 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
|
||||
}
|
||||
|
||||
/* read RGBA pixels */
|
||||
uchar *pixels = (uchar*)tex_img.resize(width, height);
|
||||
int scanlinesize = width*components*sizeof(uchar);
|
||||
uchar *pixels = (uchar*)tex_img.resize(width, height, depth);
|
||||
|
||||
if(in) {
|
||||
in->read_image(TypeDesc::UINT8,
|
||||
(uchar*)pixels + (height-1)*scanlinesize,
|
||||
AutoStride,
|
||||
-scanlinesize,
|
||||
AutoStride);
|
||||
if(depth <= 1) {
|
||||
int scanlinesize = width*components*sizeof(uchar);
|
||||
|
||||
in->read_image(TypeDesc::UINT8,
|
||||
(uchar*)pixels + (height-1)*scanlinesize,
|
||||
AutoStride,
|
||||
-scanlinesize,
|
||||
AutoStride);
|
||||
}
|
||||
else {
|
||||
in->read_image(TypeDesc::UINT8, (uchar*)pixels);
|
||||
}
|
||||
|
||||
in->close();
|
||||
delete in;
|
||||
@@ -339,7 +363,7 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
|
||||
}
|
||||
|
||||
if(components == 2) {
|
||||
for(int i = width*height-1; i >= 0; i--) {
|
||||
for(int i = width*height*depth-1; i >= 0; i--) {
|
||||
pixels[i*4+3] = pixels[i*2+1];
|
||||
pixels[i*4+2] = pixels[i*2+0];
|
||||
pixels[i*4+1] = pixels[i*2+0];
|
||||
@@ -347,7 +371,7 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
|
||||
}
|
||||
}
|
||||
else if(components == 3) {
|
||||
for(int i = width*height-1; i >= 0; i--) {
|
||||
for(int i = width*height*depth-1; i >= 0; i--) {
|
||||
pixels[i*4+3] = 255;
|
||||
pixels[i*4+2] = pixels[i*3+2];
|
||||
pixels[i*4+1] = pixels[i*3+1];
|
||||
@@ -355,7 +379,7 @@ bool ImageManager::file_load_image(Image *img, device_vector<uchar4>& tex_img)
|
||||
}
|
||||
}
|
||||
else if(components == 1) {
|
||||
for(int i = width*height-1; i >= 0; i--) {
|
||||
for(int i = width*height*depth-1; i >= 0; i--) {
|
||||
pixels[i*4+3] = 255;
|
||||
pixels[i*4+2] = pixels[i];
|
||||
pixels[i*4+1] = pixels[i];
|
||||
@@ -372,7 +396,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
|
||||
return false;
|
||||
|
||||
ImageInput *in = NULL;
|
||||
int width, height, components;
|
||||
int width, height, depth, components;
|
||||
|
||||
if(!img->builtin_data) {
|
||||
/* load image from file through OIIO */
|
||||
@@ -391,6 +415,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
|
||||
/* we only handle certain number of components */
|
||||
width = spec.width;
|
||||
height = spec.height;
|
||||
depth = spec.depth;
|
||||
components = spec.nchannels;
|
||||
}
|
||||
else {
|
||||
@@ -399,7 +424,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
|
||||
return false;
|
||||
|
||||
bool is_float;
|
||||
builtin_image_info_cb(img->filename, img->builtin_data, is_float, width, height, components);
|
||||
builtin_image_info_cb(img->filename, img->builtin_data, is_float, width, height, depth, components);
|
||||
}
|
||||
|
||||
if(!(components >= 1 && components <= 4)) {
|
||||
@@ -411,15 +436,21 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
|
||||
}
|
||||
|
||||
/* read RGBA pixels */
|
||||
float *pixels = (float*)tex_img.resize(width, height);
|
||||
int scanlinesize = width*components*sizeof(float);
|
||||
float *pixels = (float*)tex_img.resize(width, height, depth);
|
||||
|
||||
if(in) {
|
||||
in->read_image(TypeDesc::FLOAT,
|
||||
(uchar*)pixels + (height-1)*scanlinesize,
|
||||
AutoStride,
|
||||
-scanlinesize,
|
||||
AutoStride);
|
||||
if(depth <= 1) {
|
||||
int scanlinesize = width*components*sizeof(float);
|
||||
|
||||
in->read_image(TypeDesc::FLOAT,
|
||||
(uchar*)pixels + (height-1)*scanlinesize,
|
||||
AutoStride,
|
||||
-scanlinesize,
|
||||
AutoStride);
|
||||
}
|
||||
else {
|
||||
in->read_image(TypeDesc::FLOAT, (uchar*)pixels);
|
||||
}
|
||||
|
||||
in->close();
|
||||
delete in;
|
||||
@@ -429,7 +460,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
|
||||
}
|
||||
|
||||
if(components == 2) {
|
||||
for(int i = width*height-1; i >= 0; i--) {
|
||||
for(int i = width*height*depth-1; i >= 0; i--) {
|
||||
pixels[i*4+3] = pixels[i*2+1];
|
||||
pixels[i*4+2] = pixels[i*2+0];
|
||||
pixels[i*4+1] = pixels[i*2+0];
|
||||
@@ -437,7 +468,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
|
||||
}
|
||||
}
|
||||
else if(components == 3) {
|
||||
for(int i = width*height-1; i >= 0; i--) {
|
||||
for(int i = width*height*depth-1; i >= 0; i--) {
|
||||
pixels[i*4+3] = 1.0f;
|
||||
pixels[i*4+2] = pixels[i*3+2];
|
||||
pixels[i*4+1] = pixels[i*3+1];
|
||||
@@ -445,7 +476,7 @@ bool ImageManager::file_load_float_image(Image *img, device_vector<float4>& tex_
|
||||
}
|
||||
}
|
||||
else if(components == 1) {
|
||||
for(int i = width*height-1; i >= 0; i--) {
|
||||
for(int i = width*height*depth-1; i >= 0; i--) {
|
||||
pixels[i*4+3] = 1.0f;
|
||||
pixels[i*4+2] = pixels[i];
|
||||
pixels[i*4+1] = pixels[i];
|
||||
@@ -460,9 +491,7 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, int sl
|
||||
{
|
||||
if(progress->get_cancel())
|
||||
return;
|
||||
if(osl_texture_system)
|
||||
return;
|
||||
|
||||
|
||||
Image *img;
|
||||
bool is_float;
|
||||
|
||||
@@ -475,6 +504,9 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, int sl
|
||||
is_float = true;
|
||||
}
|
||||
|
||||
if(osl_texture_system && !img->builtin_data)
|
||||
return;
|
||||
|
||||
if(is_float) {
|
||||
string filename = path_filename(float_images[slot]->filename);
|
||||
progress->set_status("Updating Images", "Loading " + filename);
|
||||
@@ -556,7 +588,7 @@ void ImageManager::device_free_image(Device *device, DeviceScene *dscene, int sl
|
||||
}
|
||||
|
||||
if(img) {
|
||||
if(osl_texture_system) {
|
||||
if(osl_texture_system && !img->builtin_data) {
|
||||
#ifdef WITH_OSL
|
||||
ustring filename(images[slot]->filename);
|
||||
((OSL::TextureSystem*)osl_texture_system)->invalidate(filename);
|
||||
@@ -606,7 +638,7 @@ void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress&
|
||||
device_free_image(device, dscene, slot + tex_image_byte_start);
|
||||
}
|
||||
else if(images[slot]->need_load) {
|
||||
if(!osl_texture_system)
|
||||
if(!osl_texture_system || images[slot]->builtin_data)
|
||||
pool.push(function_bind(&ImageManager::device_load_image, this, device, dscene, slot + tex_image_byte_start, &progress));
|
||||
}
|
||||
}
|
||||
@@ -619,7 +651,7 @@ void ImageManager::device_update(Device *device, DeviceScene *dscene, Progress&
|
||||
device_free_image(device, dscene, slot);
|
||||
}
|
||||
else if(float_images[slot]->need_load) {
|
||||
if(!osl_texture_system)
|
||||
if(!osl_texture_system || float_images[slot]->builtin_data)
|
||||
pool.push(function_bind(&ImageManager::device_load_image, this, device, dscene, slot, &progress));
|
||||
}
|
||||
}
|
||||
@@ -657,6 +689,7 @@ void ImageManager::device_pack_images(Device *device, DeviceScene *dscene, Progr
|
||||
|
||||
device_vector<uchar4>& tex_img = dscene->tex_image[slot];
|
||||
|
||||
/* todo: support 3D textures, only CPU for now */
|
||||
|
||||
/* The image options are packed
|
||||
bit 0 -> periodic
|
||||
|
Reference in New Issue
Block a user