diff options
Diffstat (limited to 'intern/cycles/render/image.cpp')
-rw-r--r-- | intern/cycles/render/image.cpp | 361 |
1 files changed, 139 insertions, 222 deletions
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp index 150c742fd24..71dc85f5f03 100644 --- a/intern/cycles/render/image.cpp +++ b/intern/cycles/render/image.cpp @@ -36,59 +36,58 @@ ImageManager::ImageManager(const DeviceInfo& info) osl_texture_system = NULL; animation_frame = 0; - /* Set image limits */ + /* In case of multiple devices used we need to know type of an actual + * compute device. + * + * NOTE: We assume that all the devices are same type, otherwise we'll + * be screwed on so many levels.. + */ + DeviceType device_type = info.type; + if (device_type == DEVICE_MULTI) { + device_type = info.multi_devices[0].type; + } - /* CPU */ - if(info.type == DEVICE_CPU) { - tex_num_images[IMAGE_DATA_TYPE_BYTE4] = TEX_NUM_BYTE4_IMAGES_CPU; - tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_NUM_FLOAT4_IMAGES_CPU; - tex_num_images[IMAGE_DATA_TYPE_FLOAT] = TEX_NUM_FLOAT_IMAGES_CPU; - tex_num_images[IMAGE_DATA_TYPE_BYTE] = TEX_NUM_BYTE_IMAGES_CPU; - tex_image_byte4_start = TEX_IMAGE_BYTE4_START_CPU; - tex_image_float_start = TEX_IMAGE_FLOAT_START_CPU; - tex_image_byte_start = TEX_IMAGE_BYTE_START_CPU; + /* Set image limits */ +#define SET_TEX_IMAGES_LIMITS(ARCH) \ + { \ + tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_NUM_FLOAT4_ ## ARCH; \ + tex_num_images[IMAGE_DATA_TYPE_BYTE4] = TEX_NUM_BYTE4_ ## ARCH; \ + tex_num_images[IMAGE_DATA_TYPE_FLOAT] = TEX_NUM_FLOAT_ ## ARCH; \ + tex_num_images[IMAGE_DATA_TYPE_BYTE] = TEX_NUM_BYTE_ ## ARCH; \ + tex_start_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_START_FLOAT4_ ## ARCH; \ + tex_start_images[IMAGE_DATA_TYPE_BYTE4] = TEX_START_BYTE4_ ## ARCH; \ + tex_start_images[IMAGE_DATA_TYPE_FLOAT] = TEX_START_FLOAT_ ## ARCH; \ + tex_start_images[IMAGE_DATA_TYPE_BYTE] = TEX_START_BYTE_ ## ARCH; \ } - /* CUDA (Fermi) */ - else if((info.type == DEVICE_CUDA || info.type == DEVICE_MULTI) && !info.has_bindless_textures) { - tex_num_images[IMAGE_DATA_TYPE_BYTE4] = TEX_NUM_BYTE4_IMAGES_CUDA; - tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_NUM_FLOAT4_IMAGES_CUDA; - tex_num_images[IMAGE_DATA_TYPE_FLOAT] = TEX_NUM_FLOAT_IMAGES_CUDA; - tex_num_images[IMAGE_DATA_TYPE_BYTE] = TEX_NUM_BYTE_IMAGES_CUDA; - tex_image_byte4_start = TEX_IMAGE_BYTE4_START_CUDA; - tex_image_float_start = TEX_IMAGE_FLOAT_START_CUDA; - tex_image_byte_start = TEX_IMAGE_BYTE_START_CUDA; + + if(device_type == DEVICE_CPU) { + SET_TEX_IMAGES_LIMITS(CPU); } - /* CUDA (Kepler and above) */ - else if((info.type == DEVICE_CUDA || info.type == DEVICE_MULTI) && info.has_bindless_textures) { - tex_num_images[IMAGE_DATA_TYPE_BYTE4] = TEX_NUM_BYTE4_IMAGES_CUDA_KEPLER; - tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_NUM_FLOAT4_IMAGES_CUDA_KEPLER; - tex_num_images[IMAGE_DATA_TYPE_FLOAT] = TEX_NUM_FLOAT_IMAGES_CUDA_KEPLER; - tex_num_images[IMAGE_DATA_TYPE_BYTE] = TEX_NUM_BYTE_IMAGES_CUDA_KEPLER; - tex_image_byte4_start = TEX_IMAGE_BYTE4_START_CUDA_KEPLER; - tex_image_float_start = TEX_IMAGE_FLOAT_START_CUDA_KEPLER; - tex_image_byte_start = TEX_IMAGE_BYTE_START_CUDA_KEPLER; + else if(device_type == DEVICE_CUDA) { + if(info.has_bindless_textures) { + SET_TEX_IMAGES_LIMITS(CUDA_KEPLER); + } + else { + SET_TEX_IMAGES_LIMITS(CUDA); + } } - /* OpenCL */ - else if(info.pack_images) { - tex_num_images[IMAGE_DATA_TYPE_BYTE4] = TEX_NUM_BYTE4_IMAGES_OPENCL; - tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_NUM_FLOAT4_IMAGES_OPENCL; - tex_num_images[IMAGE_DATA_TYPE_FLOAT] = TEX_NUM_FLOAT_IMAGES_OPENCL; - tex_num_images[IMAGE_DATA_TYPE_BYTE] = TEX_NUM_BYTE_IMAGES_OPENCL; - tex_image_byte4_start = TEX_IMAGE_BYTE4_START_OPENCL; - tex_image_float_start = TEX_IMAGE_FLOAT_START_OPENCL; - tex_image_byte_start = TEX_IMAGE_BYTE_START_OPENCL; + else if(device_type == DEVICE_OPENCL) { + SET_TEX_IMAGES_LIMITS(OPENCL); } - /* Should never happen */ else { - tex_num_images[IMAGE_DATA_TYPE_BYTE4] = 0; + /* Should not happen. */ tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = 0; + tex_num_images[IMAGE_DATA_TYPE_BYTE4] = 0; tex_num_images[IMAGE_DATA_TYPE_FLOAT] = 0; tex_num_images[IMAGE_DATA_TYPE_BYTE] = 0; - tex_image_byte4_start = 0; - tex_image_float_start = 0; - tex_image_byte_start = 0; + tex_start_images[IMAGE_DATA_TYPE_FLOAT4] = 0; + tex_start_images[IMAGE_DATA_TYPE_BYTE4] = 0; + tex_start_images[IMAGE_DATA_TYPE_FLOAT] = 0; + tex_start_images[IMAGE_DATA_TYPE_BYTE] = 0; assert(0); } + +#undef SET_TEX_IMAGES_LIMITS } ImageManager::~ImageManager() @@ -207,34 +206,20 @@ ImageManager::ImageDataType ImageManager::get_image_metadata(const string& filen * to device ones and vice versa. */ int ImageManager::type_index_to_flattened_slot(int slot, ImageDataType type) { - if(type == IMAGE_DATA_TYPE_BYTE4) - return slot + tex_image_byte4_start; - else if(type == IMAGE_DATA_TYPE_FLOAT) - return slot + tex_image_float_start; - else if(type == IMAGE_DATA_TYPE_BYTE) - return slot + tex_image_byte_start; - else - return slot; + return slot + tex_start_images[type]; } int ImageManager::flattened_slot_to_type_index(int flat_slot, ImageDataType *type) { - if(flat_slot >= tex_image_byte_start) { - *type = IMAGE_DATA_TYPE_BYTE; - return flat_slot - tex_image_byte_start; - } - else if(flat_slot >= tex_image_float_start) { - *type = IMAGE_DATA_TYPE_FLOAT; - return flat_slot - tex_image_float_start; - } - else if(flat_slot >= tex_image_byte4_start) { - *type = IMAGE_DATA_TYPE_BYTE4; - return flat_slot - tex_image_byte4_start; - } - else { - *type = IMAGE_DATA_TYPE_FLOAT4; - return flat_slot; + for(int i = IMAGE_DATA_NUM_TYPES - 1; i >= 0; i--) { + if(flat_slot >= tex_start_images[i]) { + *type = (ImageDataType)i; + return flat_slot - tex_start_images[i]; + } } + + /* Should not happen. */ + return flat_slot; } string ImageManager::name_from_type(int type) @@ -280,7 +265,7 @@ int ImageManager::add_image(const string& filename, if(type == IMAGE_DATA_TYPE_FLOAT || type == IMAGE_DATA_TYPE_FLOAT4) is_float = true; - /* No single channel textures on Fermi GPUs, use available slots */ + /* No single channel textures on CUDA (Fermi) and OpenCL, use available slots */ if(type == IMAGE_DATA_TYPE_FLOAT && tex_num_images[type] == 0) type = IMAGE_DATA_TYPE_FLOAT4; if(type == IMAGE_DATA_TYPE_BYTE && tex_num_images[type] == 0) @@ -460,7 +445,8 @@ bool ImageManager::file_load_image_generic(Image *img, ImageInput **in, int &wid return true; } -bool ImageManager::file_load_byte4_image(Image *img, device_vector<uchar4>& tex_img) +template<typename T> +bool ImageManager::file_load_byte_image(Image *img, ImageDataType type, device_vector<T>& tex_img) { ImageInput *in = NULL; int width, height, depth, components; @@ -498,92 +484,59 @@ bool ImageManager::file_load_byte4_image(Image *img, device_vector<uchar4>& tex_ builtin_image_pixels_cb(img->filename, img->builtin_data, pixels); } - size_t num_pixels = ((size_t)width) * height * depth; - if(cmyk) { - /* CMYK */ - for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { - pixels[i*4+2] = (pixels[i*4+2]*pixels[i*4+3])/255; - pixels[i*4+1] = (pixels[i*4+1]*pixels[i*4+3])/255; - pixels[i*4+0] = (pixels[i*4+0]*pixels[i*4+3])/255; - pixels[i*4+3] = 255; - } - } - else if(components == 2) { - /* grayscale + alpha */ - for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, 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]; - pixels[i*4+0] = pixels[i*2+0]; + /* Check if we actually have a byte4 slot, in case components == 1, but device + * doesn't support single channel textures. */ + if(type == IMAGE_DATA_TYPE_BYTE4) { + size_t num_pixels = ((size_t)width) * height * depth; + if(cmyk) { + /* CMYK */ + for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { + pixels[i*4+2] = (pixels[i*4+2]*pixels[i*4+3])/255; + pixels[i*4+1] = (pixels[i*4+1]*pixels[i*4+3])/255; + pixels[i*4+0] = (pixels[i*4+0]*pixels[i*4+3])/255; + pixels[i*4+3] = 255; + } } - } - else if(components == 3) { - /* RGB */ - for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { - pixels[i*4+3] = 255; - pixels[i*4+2] = pixels[i*3+2]; - pixels[i*4+1] = pixels[i*3+1]; - pixels[i*4+0] = pixels[i*3+0]; + else if(components == 2) { + /* grayscale + alpha */ + for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, 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]; + pixels[i*4+0] = pixels[i*2+0]; + } } - } - else if(components == 1) { - /* grayscale */ - for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { - pixels[i*4+3] = 255; - pixels[i*4+2] = pixels[i]; - pixels[i*4+1] = pixels[i]; - pixels[i*4+0] = pixels[i]; + else if(components == 3) { + /* RGB */ + for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { + pixels[i*4+3] = 255; + pixels[i*4+2] = pixels[i*3+2]; + pixels[i*4+1] = pixels[i*3+1]; + pixels[i*4+0] = pixels[i*3+0]; + } } - } - - if(img->use_alpha == false) { - for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { - pixels[i*4+3] = 255; + else if(components == 1) { + /* grayscale */ + for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { + pixels[i*4+3] = 255; + pixels[i*4+2] = pixels[i]; + pixels[i*4+1] = pixels[i]; + pixels[i*4+0] = pixels[i]; + } } - } - - return true; -} - -bool ImageManager::file_load_byte_image(Image *img, device_vector<uchar>& tex_img) -{ - ImageInput *in = NULL; - int width, height, depth, components; - - if(!file_load_image_generic(img, &in, width, height, depth, components)) - return false; - - /* read BW pixels */ - uchar *pixels = (uchar*)tex_img.resize(width, height, depth); - if(pixels == NULL) { - return false; - } - - if(in) { - if(depth <= 1) { - int scanlinesize = width*components*sizeof(uchar); - in->read_image(TypeDesc::UINT8, - (uchar*)pixels + (((size_t)height)-1)*scanlinesize, - AutoStride, - -scanlinesize, - AutoStride); - } - else { - in->read_image(TypeDesc::UINT8, (uchar*)pixels); + if(img->use_alpha == false) { + for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { + pixels[i*4+3] = 255; + } } - - in->close(); - delete in; - } - else { - builtin_image_pixels_cb(img->filename, img->builtin_data, pixels); } return true; } -bool ImageManager::file_load_float4_image(Image *img, device_vector<float4>& tex_img) +template<typename T> +bool ImageManager::file_load_float_image(Image *img, ImageDataType type, device_vector<T>& tex_img) { ImageInput *in = NULL; int width, height, depth, components; @@ -641,88 +594,52 @@ bool ImageManager::file_load_float4_image(Image *img, device_vector<float4>& tex builtin_image_float_pixels_cb(img->filename, img->builtin_data, pixels); } - size_t num_pixels = ((size_t)width) * height * depth; - if(cmyk) { - /* CMYK */ - for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { - pixels[i*4+3] = 255; - pixels[i*4+2] = (pixels[i*4+2]*pixels[i*4+3])/255; - pixels[i*4+1] = (pixels[i*4+1]*pixels[i*4+3])/255; - pixels[i*4+0] = (pixels[i*4+0]*pixels[i*4+3])/255; - } - } - else if(components == 2) { - /* grayscale + alpha */ - for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, 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]; - pixels[i*4+0] = pixels[i*2+0]; + /* Check if we actually have a float4 slot, in case components == 1, but device + * doesn't support single channel textures. */ + if(type == IMAGE_DATA_TYPE_FLOAT4) { + size_t num_pixels = ((size_t)width) * height * depth; + if(cmyk) { + /* CMYK */ + for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { + pixels[i*4+3] = 255; + pixels[i*4+2] = (pixels[i*4+2]*pixels[i*4+3])/255; + pixels[i*4+1] = (pixels[i*4+1]*pixels[i*4+3])/255; + pixels[i*4+0] = (pixels[i*4+0]*pixels[i*4+3])/255; + } } - } - else if(components == 3) { - /* RGB */ - for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { - pixels[i*4+3] = 1.0f; - pixels[i*4+2] = pixels[i*3+2]; - pixels[i*4+1] = pixels[i*3+1]; - pixels[i*4+0] = pixels[i*3+0]; + else if(components == 2) { + /* grayscale + alpha */ + for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, 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]; + pixels[i*4+0] = pixels[i*2+0]; + } } - } - else if(components == 1) { - /* grayscale */ - for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { - pixels[i*4+3] = 1.0f; - pixels[i*4+2] = pixels[i]; - pixels[i*4+1] = pixels[i]; - pixels[i*4+0] = pixels[i]; + else if(components == 3) { + /* RGB */ + for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { + pixels[i*4+3] = 1.0f; + pixels[i*4+2] = pixels[i*3+2]; + pixels[i*4+1] = pixels[i*3+1]; + pixels[i*4+0] = pixels[i*3+0]; + } } - } - - if(img->use_alpha == false) { - for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { - pixels[i*4+3] = 1.0f; + else if(components == 1) { + /* grayscale */ + for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { + pixels[i*4+3] = 1.0f; + pixels[i*4+2] = pixels[i]; + pixels[i*4+1] = pixels[i]; + pixels[i*4+0] = pixels[i]; + } } - } - - return true; -} - -bool ImageManager::file_load_float_image(Image *img, device_vector<float>& tex_img) -{ - ImageInput *in = NULL; - int width, height, depth, components; - - if(!file_load_image_generic(img, &in, width, height, depth, components)) - return false; - - /* read BW pixels */ - float *pixels = (float*)tex_img.resize(width, height, depth); - if(pixels == NULL) { - return false; - } - if(in) { - float *readpixels = pixels; - - if(depth <= 1) { - int scanlinesize = width*components*sizeof(float); - - in->read_image(TypeDesc::FLOAT, - (uchar*)readpixels + (height-1)*scanlinesize, - AutoStride, - -scanlinesize, - AutoStride); - } - else { - in->read_image(TypeDesc::FLOAT, (uchar*)readpixels); + if(img->use_alpha == false) { + for(size_t i = num_pixels-1, pixel = 0; pixel < num_pixels; pixel++, i--) { + pixels[i*4+3] = 1.0f; + } } - - in->close(); - delete in; - } - else { - builtin_image_float_pixels_cb(img->filename, img->builtin_data, pixels); } return true; @@ -760,7 +677,7 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageD device->tex_free(tex_img); } - if(!file_load_float4_image(img, tex_img)) { + if(!file_load_float_image(img, type, tex_img)) { /* on failure to load, we set a 1x1 pixels pink image */ float *pixels = (float*)tex_img.resize(1, 1); @@ -786,7 +703,7 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageD device->tex_free(tex_img); } - if(!file_load_float_image(img, tex_img)) { + if(!file_load_float_image(img, type, tex_img)) { /* on failure to load, we set a 1x1 pixels pink image */ float *pixels = (float*)tex_img.resize(1, 1); @@ -809,7 +726,7 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageD device->tex_free(tex_img); } - if(!file_load_byte4_image(img, tex_img)) { + if(!file_load_byte_image(img, type, tex_img)) { /* on failure to load, we set a 1x1 pixels pink image */ uchar *pixels = (uchar*)tex_img.resize(1, 1); @@ -835,7 +752,7 @@ void ImageManager::device_load_image(Device *device, DeviceScene *dscene, ImageD device->tex_free(tex_img); } - if(!file_load_byte_image(img, tex_img)) { + if(!file_load_byte_image(img, type, tex_img)) { /* on failure to load, we set a 1x1 pixels pink image */ uchar *pixels = (uchar*)tex_img.resize(1, 1); |