Changeset View
Changeset View
Standalone View
Standalone View
intern/cycles/render/image.cpp
| Show First 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | ImageManager::ImageManager(const DeviceInfo& info) | ||||
| * be screwed on so many levels.. | * be screwed on so many levels.. | ||||
| */ | */ | ||||
| DeviceType device_type = info.type; | DeviceType device_type = info.type; | ||||
| if(device_type == DEVICE_MULTI) { | if(device_type == DEVICE_MULTI) { | ||||
| device_type = info.multi_devices[0].type; | device_type = info.multi_devices[0].type; | ||||
| } | } | ||||
| /* Set image limits */ | /* Set image limits */ | ||||
| #define SET_TEX_IMAGES_LIMITS(ARCH) \ | max_num_images = TEX_NUM_MAX; | ||||
| { \ | has_half_images = true; | ||||
| tex_num_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_NUM_FLOAT4_ ## ARCH; \ | cuda_fermi_limits = false; | ||||
| tex_num_images[IMAGE_DATA_TYPE_BYTE4] = TEX_NUM_BYTE4_ ## ARCH; \ | |||||
| tex_num_images[IMAGE_DATA_TYPE_HALF4] = TEX_NUM_HALF4_ ## ARCH; \ | if(device_type == DEVICE_CUDA) { | ||||
| tex_num_images[IMAGE_DATA_TYPE_FLOAT] = TEX_NUM_FLOAT_ ## ARCH; \ | if(!info.has_bindless_textures) { | ||||
| tex_num_images[IMAGE_DATA_TYPE_BYTE] = TEX_NUM_BYTE_ ## ARCH; \ | /* CUDA Fermi hardware (SM 2.x) has a hard limit on the number of textures */ | ||||
| tex_num_images[IMAGE_DATA_TYPE_HALF] = TEX_NUM_HALF_ ## ARCH; \ | cuda_fermi_limits = true; | ||||
| tex_start_images[IMAGE_DATA_TYPE_FLOAT4] = TEX_START_FLOAT4_ ## ARCH; \ | has_half_images = false; | ||||
| tex_start_images[IMAGE_DATA_TYPE_BYTE4] = TEX_START_BYTE4_ ## ARCH; \ | |||||
| tex_start_images[IMAGE_DATA_TYPE_HALF4] = TEX_START_HALF4_ ## ARCH; \ | |||||
| tex_start_images[IMAGE_DATA_TYPE_FLOAT] = TEX_START_FLOAT_ ## ARCH; \ | |||||
| tex_start_images[IMAGE_DATA_TYPE_BYTE] = TEX_START_BYTE_ ## ARCH; \ | |||||
| tex_start_images[IMAGE_DATA_TYPE_HALF] = TEX_START_HALF_ ## ARCH; \ | |||||
| } | |||||
| if(device_type == DEVICE_CPU) { | |||||
| SET_TEX_IMAGES_LIMITS(CPU); | |||||
| } | |||||
| else if(device_type == DEVICE_CUDA) { | |||||
| if(info.has_bindless_textures) { | |||||
| SET_TEX_IMAGES_LIMITS(CUDA_KEPLER); | |||||
| } | |||||
| else { | |||||
| SET_TEX_IMAGES_LIMITS(CUDA); | |||||
| } | } | ||||
| } | } | ||||
| else if(device_type == DEVICE_OPENCL) { | else if(device_type == DEVICE_OPENCL) { | ||||
| SET_TEX_IMAGES_LIMITS(OPENCL); | has_half_images = false; | ||||
| } | |||||
| else { | |||||
| /* 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_HALF4] = 0; | |||||
| tex_num_images[IMAGE_DATA_TYPE_FLOAT] = 0; | |||||
| tex_num_images[IMAGE_DATA_TYPE_BYTE] = 0; | |||||
| tex_num_images[IMAGE_DATA_TYPE_HALF] = 0; | |||||
| tex_start_images[IMAGE_DATA_TYPE_FLOAT4] = 0; | |||||
| tex_start_images[IMAGE_DATA_TYPE_BYTE4] = 0; | |||||
| tex_start_images[IMAGE_DATA_TYPE_HALF4] = 0; | |||||
| tex_start_images[IMAGE_DATA_TYPE_FLOAT] = 0; | |||||
| tex_start_images[IMAGE_DATA_TYPE_BYTE] = 0; | |||||
| tex_start_images[IMAGE_DATA_TYPE_HALF] = 0; | |||||
| assert(0); | |||||
| } | } | ||||
| #undef SET_TEX_IMAGES_LIMITS | for(size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) { | ||||
| tex_num_images[type] = 0; | |||||
| } | |||||
| } | } | ||||
| ImageManager::~ImageManager() | ImageManager::~ImageManager() | ||||
| { | { | ||||
| for(size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) { | for(size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) { | ||||
| for(size_t slot = 0; slot < images[type].size(); slot++) | for(size_t slot = 0; slot < images[type].size(); slot++) | ||||
| assert(!images[type][slot]); | assert(!images[type][slot]); | ||||
| } | } | ||||
| Show All 20 Lines | for(size_t type = 0; type < IMAGE_DATA_NUM_TYPES; type++) { | ||||
| return true; | return true; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| ImageManager::ImageDataType ImageManager::get_image_metadata(const string& filename, | ImageDataType ImageManager::get_image_metadata(const string& filename, | ||||
| void *builtin_data, | void *builtin_data, | ||||
| bool& is_linear) | bool& is_linear) | ||||
| { | { | ||||
| bool is_float = false, is_half = false; | bool is_float = false, is_half = false; | ||||
| is_linear = false; | is_linear = false; | ||||
| int channels = 4; | int channels = 4; | ||||
| if(builtin_data) { | if(builtin_data) { | ||||
| ▲ Show 20 Lines • Show All 76 Lines • ▼ Show 20 Lines | ImageDataType ImageManager::get_image_metadata(const string& filename, | ||||
| else if(is_float) { | else if(is_float) { | ||||
| return (channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_FLOAT; | return (channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_FLOAT; | ||||
| } | } | ||||
| else { | else { | ||||
| return (channels > 1) ? IMAGE_DATA_TYPE_BYTE4 : IMAGE_DATA_TYPE_BYTE; | return (channels > 1) ? IMAGE_DATA_TYPE_BYTE4 : IMAGE_DATA_TYPE_BYTE; | ||||
| } | } | ||||
| } | } | ||||
| /* We use a consecutive slot counting scheme on the devices, in order | /* The lower three bits of a device texture slot number indicate its type. | ||||
| * float4, byte4, half4, float, byte, half. | |||||
| * These functions convert the slot ids from ImageManager "images" ones | * These functions convert the slot ids from ImageManager "images" ones | ||||
| * to device ones and vice versa. */ | * to device ones and vice versa. | ||||
sergey: Would suggest making it a constant similar to primitive type so if we add more types we don't… | |||||
| * | |||||
| * There are special cases for CUDA Fermi, since there we have only 90 image texture | |||||
| * slots available and shold keep the flattended numbers in the 0-89 range. | |||||
| */ | |||||
| int ImageManager::type_index_to_flattened_slot(int slot, ImageDataType type) | int ImageManager::type_index_to_flattened_slot(int slot, ImageDataType type) | ||||
Done Inline ActionsWe don't use c++ casts in Cycles, we use C-like casts. sergey: We don't use c++ casts in Cycles, we use C-like casts. | |||||
| { | { | ||||
| return slot + tex_start_images[type]; | if(cuda_fermi_limits) { | ||||
Done Inline ActionsSame as above. sergey: Same as above. | |||||
| if(type == IMAGE_DATA_TYPE_BYTE4) { | |||||
| return slot + TEX_START_BYTE4_CUDA; | |||||
| } | |||||
| else { | |||||
| return slot; | |||||
| } | |||||
| } | |||||
| return (slot << IMAGE_DATA_TYPE_SHIFT) | (type); | |||||
| } | } | ||||
| int ImageManager::flattened_slot_to_type_index(int flat_slot, ImageDataType *type) | int ImageManager::flattened_slot_to_type_index(int flat_slot, ImageDataType *type) | ||||
| { | { | ||||
| for(int i = IMAGE_DATA_NUM_TYPES - 1; i >= 0; i--) { | if(cuda_fermi_limits) { | ||||
| if(flat_slot >= tex_start_images[i]) { | if(flat_slot >= 4) { | ||||
| *type = (ImageDataType)i; | *type = IMAGE_DATA_TYPE_BYTE4; | ||||
| return flat_slot - tex_start_images[i]; | return flat_slot - TEX_START_BYTE4_CUDA; | ||||
Done Inline ActionsShould these magic numbers be constants somewhere? smellslikedonkey: Should these magic numbers be constants somewhere? | |||||
| } | |||||
| else { | |||||
| *type = IMAGE_DATA_TYPE_FLOAT4; | |||||
| return flat_slot; | |||||
| } | } | ||||
| } | } | ||||
| /* Should not happen. */ | *type = (ImageDataType)(flat_slot & IMAGE_DATA_TYPE_MASK); | ||||
| return flat_slot; | return flat_slot >> IMAGE_DATA_TYPE_SHIFT; | ||||
| } | } | ||||
| string ImageManager::name_from_type(int type) | string ImageManager::name_from_type(int type) | ||||
| { | { | ||||
| if(type == IMAGE_DATA_TYPE_FLOAT4) | if(type == IMAGE_DATA_TYPE_FLOAT4) | ||||
| return "float4"; | return "float4"; | ||||
| else if(type == IMAGE_DATA_TYPE_FLOAT) | else if(type == IMAGE_DATA_TYPE_FLOAT) | ||||
| return "float"; | return "float"; | ||||
| Show All 36 Lines | int ImageManager::add_image(const string& filename, | ||||
| ImageDataType type = get_image_metadata(filename, builtin_data, is_linear); | ImageDataType type = get_image_metadata(filename, builtin_data, is_linear); | ||||
| thread_scoped_lock device_lock(device_mutex); | thread_scoped_lock device_lock(device_mutex); | ||||
| /* Check whether it's a float texture. */ | /* Check whether it's a float texture. */ | ||||
| is_float = (type == IMAGE_DATA_TYPE_FLOAT || type == IMAGE_DATA_TYPE_FLOAT4); | is_float = (type == IMAGE_DATA_TYPE_FLOAT || type == IMAGE_DATA_TYPE_FLOAT4); | ||||
| /* No single channel and half textures on CUDA (Fermi) and no half on OpenCL, use available slots */ | /* No single channel and half textures on CUDA (Fermi) and no half on OpenCL, use available slots */ | ||||
Done Inline ActionsNot sure why the comment is changed, we still convert single channel and half slots which are not available on fermi to other slot types. It's easier to read a one sentence comment, rather than read 4 if/else lines. dingto: Not sure why the comment is changed, we still convert single channel and half slots which are… | |||||
Done Inline ActionsInitially I thought I could get half precision textures on Fermi too by assigning the texture slots as needed, but that ended up not being the case. This commend was a relict of that. swerner: Initially I thought I could get half precision textures on Fermi too by assigning the texture… | |||||
| if((type == IMAGE_DATA_TYPE_FLOAT || | if(type == IMAGE_DATA_TYPE_HALF4 && !has_half_images) { | ||||
| type == IMAGE_DATA_TYPE_HALF4 || | type = IMAGE_DATA_TYPE_FLOAT4; | ||||
| type == IMAGE_DATA_TYPE_HALF) && | } else if(type == IMAGE_DATA_TYPE_HALF && !has_half_images) { | ||||
| tex_num_images[type] == 0) { | type = IMAGE_DATA_TYPE_FLOAT; | ||||
| } | |||||
| if(type == IMAGE_DATA_TYPE_FLOAT && cuda_fermi_limits) { | |||||
Done Inline ActionsCode style (no gap between if and brace), also wrong in other places. dingto: Code style (no gap between if and brace), also wrong in other places. | |||||
| type = IMAGE_DATA_TYPE_FLOAT4; | type = IMAGE_DATA_TYPE_FLOAT4; | ||||
| } | } | ||||
| if(type == IMAGE_DATA_TYPE_BYTE && tex_num_images[type] == 0) { | else if(type == IMAGE_DATA_TYPE_BYTE && cuda_fermi_limits) { | ||||
| type = IMAGE_DATA_TYPE_BYTE4; | type = IMAGE_DATA_TYPE_BYTE4; | ||||
| } | } | ||||
| /* Fnd existing image. */ | /* Fnd existing image. */ | ||||
| for(slot = 0; slot < images[type].size(); slot++) { | for(slot = 0; slot < images[type].size(); slot++) { | ||||
| img = images[type][slot]; | img = images[type][slot]; | ||||
| if(img && image_equals(img, | if(img && image_equals(img, | ||||
| filename, | filename, | ||||
| Show All 16 Lines | int ImageManager::add_image(const string& filename, | ||||
| } | } | ||||
| /* Find free slot. */ | /* Find free slot. */ | ||||
| for(slot = 0; slot < images[type].size(); slot++) { | for(slot = 0; slot < images[type].size(); slot++) { | ||||
| if(!images[type][slot]) | if(!images[type][slot]) | ||||
| break; | break; | ||||
| } | } | ||||
| if(slot == images[type].size()) { | /* Count if we're over the limit */ | ||||
| /* Max images limit reached. */ | if(cuda_fermi_limits) { | ||||
| if(images[type].size() == tex_num_images[type]) { | if(tex_num_images[IMAGE_DATA_TYPE_BYTE4] == TEX_NUM_BYTE4_CUDA | ||||
| || tex_num_images[IMAGE_DATA_TYPE_FLOAT4] == TEX_NUM_FLOAT4_CUDA) | |||||
| { | |||||
| printf("ImageManager::add_image: Reached %s image limit (%d), skipping '%s'\n", | printf("ImageManager::add_image: Reached %s image limit (%d), skipping '%s'\n", | ||||
| name_from_type(type).c_str(), tex_num_images[type], filename.c_str()); | name_from_type(type).c_str(), tex_num_images[type], filename.c_str()); | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| } | |||||
| else { | |||||
| /* Very unlikely, since max_num_images is insanely big. But better safe than sorry. */ | |||||
| int tex_count = 0; | |||||
| for (int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) { | |||||
| tex_count += tex_num_images[type]; | |||||
| } | |||||
| if(tex_count > max_num_images) { | |||||
| printf("ImageManager::add_image: Reached image limit (%d), skipping '%s'\n", | |||||
| max_num_images, filename.c_str()); | |||||
| return -1; | |||||
| } | |||||
| } | |||||
| if(slot == images[type].size()) { | |||||
| images[type].resize(images[type].size() + 1); | images[type].resize(images[type].size() + 1); | ||||
| } | } | ||||
| /* Add new image. */ | /* Add new image. */ | ||||
| img = new Image(); | img = new Image(); | ||||
| img->filename = filename; | img->filename = filename; | ||||
| img->builtin_data = builtin_data; | img->builtin_data = builtin_data; | ||||
| img->need_load = true; | img->need_load = true; | ||||
| img->animated = animated; | img->animated = animated; | ||||
| img->frame = frame; | img->frame = frame; | ||||
| img->interpolation = interpolation; | img->interpolation = interpolation; | ||||
| img->extension = extension; | img->extension = extension; | ||||
| img->users = 1; | img->users = 1; | ||||
| img->use_alpha = use_alpha; | img->use_alpha = use_alpha; | ||||
| images[type][slot] = img; | images[type][slot] = img; | ||||
| ++tex_num_images[type]; | |||||
| need_update = true; | need_update = true; | ||||
| return type_index_to_flattened_slot(slot, type); | return type_index_to_flattened_slot(slot, type); | ||||
| } | } | ||||
| void ImageManager::remove_image(int flat_slot) | void ImageManager::remove_image(int flat_slot) | ||||
| { | { | ||||
| ImageDataType type; | ImageDataType type; | ||||
| ▲ Show 20 Lines • Show All 287 Lines • ▼ Show 20 Lines | void ImageManager::device_load_image(Device *device, | ||||
| string filename = path_filename(images[type][slot]->filename); | string filename = path_filename(images[type][slot]->filename); | ||||
| progress->set_status("Updating Images", "Loading " + filename); | progress->set_status("Updating Images", "Loading " + filename); | ||||
| const int texture_limit = scene->params.texture_limit; | const int texture_limit = scene->params.texture_limit; | ||||
| /* Slot assignment */ | /* Slot assignment */ | ||||
| int flat_slot = type_index_to_flattened_slot(slot, type); | int flat_slot = type_index_to_flattened_slot(slot, type); | ||||
| string name; | string name = string_printf("__tex_image_%s_%03d", name_from_type(type).c_str(), flat_slot); | ||||
| if(flat_slot >= 100) | |||||
| name = string_printf("__tex_image_%s_%d", name_from_type(type).c_str(), flat_slot); | |||||
| else if(flat_slot >= 10) | |||||
| name = string_printf("__tex_image_%s_0%d", name_from_type(type).c_str(), flat_slot); | |||||
| else | |||||
| name = string_printf("__tex_image_%s_00%d", name_from_type(type).c_str(), flat_slot); | |||||
| if(type == IMAGE_DATA_TYPE_FLOAT4) { | if(type == IMAGE_DATA_TYPE_FLOAT4) { | ||||
| device_vector<float4>& tex_img = dscene->tex_float4_image[slot]; | if(dscene->tex_float4_image[slot] == NULL) | ||||
| dscene->tex_float4_image[slot] = new device_vector<float4>(); | |||||
| device_vector<float4>& tex_img = *dscene->tex_float4_image[slot]; | |||||
| if(tex_img.device_pointer) { | if(tex_img.device_pointer) { | ||||
| thread_scoped_lock device_lock(device_mutex); | thread_scoped_lock device_lock(device_mutex); | ||||
| device->tex_free(tex_img); | device->tex_free(tex_img); | ||||
| } | } | ||||
| if(!file_load_image<TypeDesc::FLOAT, float>(img, | if(!file_load_image<TypeDesc::FLOAT, float>(img, | ||||
| type, | type, | ||||
| Show All 13 Lines | if(!pack_images) { | ||||
| thread_scoped_lock device_lock(device_mutex); | thread_scoped_lock device_lock(device_mutex); | ||||
| device->tex_alloc(name.c_str(), | device->tex_alloc(name.c_str(), | ||||
| tex_img, | tex_img, | ||||
| img->interpolation, | img->interpolation, | ||||
| img->extension); | img->extension); | ||||
| } | } | ||||
| } | } | ||||
| else if(type == IMAGE_DATA_TYPE_FLOAT) { | else if(type == IMAGE_DATA_TYPE_FLOAT) { | ||||
| device_vector<float>& tex_img = dscene->tex_float_image[slot]; | if(dscene->tex_float_image[slot] == NULL) | ||||
| dscene->tex_float_image[slot] = new device_vector<float>(); | |||||
| device_vector<float>& tex_img = *dscene->tex_float_image[slot]; | |||||
| if(tex_img.device_pointer) { | if(tex_img.device_pointer) { | ||||
| thread_scoped_lock device_lock(device_mutex); | thread_scoped_lock device_lock(device_mutex); | ||||
| device->tex_free(tex_img); | device->tex_free(tex_img); | ||||
| } | } | ||||
| if(!file_load_image<TypeDesc::FLOAT, float>(img, | if(!file_load_image<TypeDesc::FLOAT, float>(img, | ||||
| type, | type, | ||||
| Show All 10 Lines | if(!pack_images) { | ||||
| thread_scoped_lock device_lock(device_mutex); | thread_scoped_lock device_lock(device_mutex); | ||||
| device->tex_alloc(name.c_str(), | device->tex_alloc(name.c_str(), | ||||
| tex_img, | tex_img, | ||||
| img->interpolation, | img->interpolation, | ||||
| img->extension); | img->extension); | ||||
| } | } | ||||
| } | } | ||||
| else if(type == IMAGE_DATA_TYPE_BYTE4) { | else if(type == IMAGE_DATA_TYPE_BYTE4) { | ||||
| device_vector<uchar4>& tex_img = dscene->tex_byte4_image[slot]; | if(dscene->tex_byte4_image[slot] == NULL) | ||||
| dscene->tex_byte4_image[slot] = new device_vector<uchar4>(); | |||||
| device_vector<uchar4>& tex_img = *dscene->tex_byte4_image[slot]; | |||||
| if(tex_img.device_pointer) { | if(tex_img.device_pointer) { | ||||
| thread_scoped_lock device_lock(device_mutex); | thread_scoped_lock device_lock(device_mutex); | ||||
| device->tex_free(tex_img); | device->tex_free(tex_img); | ||||
| } | } | ||||
| if(!file_load_image<TypeDesc::UINT8, uchar>(img, | if(!file_load_image<TypeDesc::UINT8, uchar>(img, | ||||
| type, | type, | ||||
| Show All 13 Lines | if(!pack_images) { | ||||
| thread_scoped_lock device_lock(device_mutex); | thread_scoped_lock device_lock(device_mutex); | ||||
| device->tex_alloc(name.c_str(), | device->tex_alloc(name.c_str(), | ||||
| tex_img, | tex_img, | ||||
| img->interpolation, | img->interpolation, | ||||
| img->extension); | img->extension); | ||||
| } | } | ||||
| } | } | ||||
| else if(type == IMAGE_DATA_TYPE_BYTE){ | else if(type == IMAGE_DATA_TYPE_BYTE){ | ||||
| device_vector<uchar>& tex_img = dscene->tex_byte_image[slot]; | if(dscene->tex_byte_image[slot] == NULL) | ||||
| dscene->tex_byte_image[slot] = new device_vector<uchar>(); | |||||
| device_vector<uchar>& tex_img = *dscene->tex_byte_image[slot]; | |||||
| if(tex_img.device_pointer) { | if(tex_img.device_pointer) { | ||||
| thread_scoped_lock device_lock(device_mutex); | thread_scoped_lock device_lock(device_mutex); | ||||
| device->tex_free(tex_img); | device->tex_free(tex_img); | ||||
| } | } | ||||
| if(!file_load_image<TypeDesc::UINT8, uchar>(img, | if(!file_load_image<TypeDesc::UINT8, uchar>(img, | ||||
| type, | type, | ||||
| Show All 9 Lines | if(!pack_images) { | ||||
| thread_scoped_lock device_lock(device_mutex); | thread_scoped_lock device_lock(device_mutex); | ||||
| device->tex_alloc(name.c_str(), | device->tex_alloc(name.c_str(), | ||||
| tex_img, | tex_img, | ||||
| img->interpolation, | img->interpolation, | ||||
| img->extension); | img->extension); | ||||
| } | } | ||||
| } | } | ||||
| else if(type == IMAGE_DATA_TYPE_HALF4){ | else if(type == IMAGE_DATA_TYPE_HALF4){ | ||||
| device_vector<half4>& tex_img = dscene->tex_half4_image[slot]; | if(dscene->tex_half4_image[slot] == NULL) | ||||
| dscene->tex_half4_image[slot] = new device_vector<half4>(); | |||||
| device_vector<half4>& tex_img = *dscene->tex_half4_image[slot]; | |||||
| if(tex_img.device_pointer) { | if(tex_img.device_pointer) { | ||||
| thread_scoped_lock device_lock(device_mutex); | thread_scoped_lock device_lock(device_mutex); | ||||
| device->tex_free(tex_img); | device->tex_free(tex_img); | ||||
| } | } | ||||
| if(!file_load_image<TypeDesc::HALF, half>(img, | if(!file_load_image<TypeDesc::HALF, half>(img, | ||||
| type, | type, | ||||
| Show All 12 Lines | if(!pack_images) { | ||||
| thread_scoped_lock device_lock(device_mutex); | thread_scoped_lock device_lock(device_mutex); | ||||
| device->tex_alloc(name.c_str(), | device->tex_alloc(name.c_str(), | ||||
| tex_img, | tex_img, | ||||
| img->interpolation, | img->interpolation, | ||||
| img->extension); | img->extension); | ||||
| } | } | ||||
| } | } | ||||
| else if(type == IMAGE_DATA_TYPE_HALF){ | else if(type == IMAGE_DATA_TYPE_HALF){ | ||||
| device_vector<half>& tex_img = dscene->tex_half_image[slot]; | if(dscene->tex_half_image[slot] == NULL) | ||||
| dscene->tex_half_image[slot] = new device_vector<half>(); | |||||
| device_vector<half>& tex_img = *dscene->tex_half_image[slot]; | |||||
| if(tex_img.device_pointer) { | if(tex_img.device_pointer) { | ||||
| thread_scoped_lock device_lock(device_mutex); | thread_scoped_lock device_lock(device_mutex); | ||||
| device->tex_free(tex_img); | device->tex_free(tex_img); | ||||
| } | } | ||||
| if(!file_load_image<TypeDesc::HALF, half>(img, | if(!file_load_image<TypeDesc::HALF, half>(img, | ||||
| type, | type, | ||||
| Show All 23 Lines | void ImageManager::device_free_image(Device *device, DeviceScene *dscene, ImageDataType type, int slot) | ||||
| if(img) { | if(img) { | ||||
| if(osl_texture_system && !img->builtin_data) { | if(osl_texture_system && !img->builtin_data) { | ||||
| #ifdef WITH_OSL | #ifdef WITH_OSL | ||||
| ustring filename(images[type][slot]->filename); | ustring filename(images[type][slot]->filename); | ||||
| ((OSL::TextureSystem*)osl_texture_system)->invalidate(filename); | ((OSL::TextureSystem*)osl_texture_system)->invalidate(filename); | ||||
| #endif | #endif | ||||
| } | } | ||||
| else if(type == IMAGE_DATA_TYPE_FLOAT4) { | else { | ||||
| device_vector<float4>& tex_img = dscene->tex_float4_image[slot]; | device_memory *tex_img = NULL; | ||||
| switch(type) { | |||||
| if(tex_img.device_pointer) { | case IMAGE_DATA_TYPE_FLOAT4: | ||||
| thread_scoped_lock device_lock(device_mutex); | tex_img = dscene->tex_float4_image[slot]; | ||||
| device->tex_free(tex_img); | dscene->tex_float4_image[slot] = NULL; | ||||
| } | break; | ||||
| case IMAGE_DATA_TYPE_FLOAT: | |||||
| tex_img.clear(); | tex_img = dscene->tex_float_image[slot]; | ||||
| } | dscene->tex_float_image[slot] = NULL; | ||||
| else if(type == IMAGE_DATA_TYPE_FLOAT) { | break; | ||||
| device_vector<float>& tex_img = dscene->tex_float_image[slot]; | case IMAGE_DATA_TYPE_BYTE: | ||||
| tex_img = dscene->tex_byte_image[slot]; | |||||
| if(tex_img.device_pointer) { | dscene->tex_byte_image[slot]= NULL; | ||||
| thread_scoped_lock device_lock(device_mutex); | break; | ||||
| device->tex_free(tex_img); | case IMAGE_DATA_TYPE_BYTE4: | ||||
| } | tex_img = dscene->tex_byte4_image[slot]; | ||||
| dscene->tex_byte4_image[slot]= NULL; | |||||
| tex_img.clear(); | break; | ||||
| } | case IMAGE_DATA_TYPE_HALF: | ||||
| else if(type == IMAGE_DATA_TYPE_BYTE4) { | tex_img = dscene->tex_half_image[slot]; | ||||
| device_vector<uchar4>& tex_img = dscene->tex_byte4_image[slot]; | dscene->tex_half_image[slot]= NULL; | ||||
| break; | |||||
| if(tex_img.device_pointer) { | case IMAGE_DATA_TYPE_HALF4: | ||||
| thread_scoped_lock device_lock(device_mutex); | tex_img = dscene->tex_half4_image[slot]; | ||||
| device->tex_free(tex_img); | dscene->tex_half4_image[slot]= NULL; | ||||
| } | break; | ||||
| default: | |||||
| tex_img.clear(); | assert(0); | ||||
| } | tex_img = NULL; | ||||
| else if(type == IMAGE_DATA_TYPE_BYTE){ | |||||
| device_vector<uchar>& tex_img = dscene->tex_byte_image[slot]; | |||||
| if(tex_img.device_pointer) { | |||||
| thread_scoped_lock device_lock(device_mutex); | |||||
| device->tex_free(tex_img); | |||||
| } | |||||
| tex_img.clear(); | |||||
| } | } | ||||
| else if(type == IMAGE_DATA_TYPE_HALF4){ | if(tex_img) { | ||||
| device_vector<half4>& tex_img = dscene->tex_half4_image[slot]; | if(tex_img->device_pointer) { | ||||
| if(tex_img.device_pointer) { | |||||
| thread_scoped_lock device_lock(device_mutex); | thread_scoped_lock device_lock(device_mutex); | ||||
| device->tex_free(tex_img); | device->tex_free(*tex_img); | ||||
| } | } | ||||
| tex_img.clear(); | delete tex_img; | ||||
| } | } | ||||
| else if(type == IMAGE_DATA_TYPE_HALF){ | |||||
| device_vector<half>& tex_img = dscene->tex_half_image[slot]; | |||||
| if(tex_img.device_pointer) { | |||||
| thread_scoped_lock device_lock(device_mutex); | |||||
| device->tex_free(tex_img); | |||||
| } | |||||
| tex_img.clear(); | |||||
| } | } | ||||
| delete images[type][slot]; | delete images[type][slot]; | ||||
| images[type][slot] = NULL; | images[type][slot] = NULL; | ||||
| --tex_num_images[type]; | |||||
| } | } | ||||
| } | } | ||||
| void ImageManager::device_update(Device *device, | void ImageManager::device_update(Device *device, | ||||
| DeviceScene *dscene, | DeviceScene *dscene, | ||||
| Scene *scene, | Scene *scene, | ||||
| Progress& progress) | Progress& progress) | ||||
| { | { | ||||
| if(!need_update) | if(!need_update) | ||||
| return; | return; | ||||
| TaskPool pool; | TaskPool pool; | ||||
| for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) { | for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) { | ||||
| switch(type) { | |||||
| case IMAGE_DATA_TYPE_BYTE4: | |||||
| if(dscene->tex_byte4_image.size() <= tex_num_images[IMAGE_DATA_TYPE_BYTE4]) | |||||
| dscene->tex_byte4_image.resize(tex_num_images[IMAGE_DATA_TYPE_BYTE4]); | |||||
| break; | |||||
| case IMAGE_DATA_TYPE_FLOAT4: | |||||
| if(dscene->tex_float4_image.size() <= tex_num_images[IMAGE_DATA_TYPE_FLOAT4]) | |||||
| dscene->tex_float4_image.resize(tex_num_images[IMAGE_DATA_TYPE_FLOAT4]); | |||||
| break; | |||||
| case IMAGE_DATA_TYPE_BYTE: | |||||
| if(dscene->tex_byte_image.size() <= tex_num_images[IMAGE_DATA_TYPE_BYTE]) | |||||
| dscene->tex_byte_image.resize(tex_num_images[IMAGE_DATA_TYPE_BYTE]); | |||||
| break; | |||||
| case IMAGE_DATA_TYPE_FLOAT: | |||||
| if(dscene->tex_float_image.size() <= tex_num_images[IMAGE_DATA_TYPE_FLOAT]) | |||||
| dscene->tex_float_image.resize(tex_num_images[IMAGE_DATA_TYPE_FLOAT]); | |||||
| break; | |||||
| case IMAGE_DATA_TYPE_HALF4: | |||||
| if(dscene->tex_half4_image.size() <= tex_num_images[IMAGE_DATA_TYPE_HALF4]) | |||||
| dscene->tex_half4_image.resize(tex_num_images[IMAGE_DATA_TYPE_HALF4]); | |||||
| break; | |||||
| case IMAGE_DATA_TYPE_HALF: | |||||
| if(dscene->tex_half_image.size() <= tex_num_images[IMAGE_DATA_TYPE_HALF]) | |||||
| dscene->tex_half_image.resize(tex_num_images[IMAGE_DATA_TYPE_HALF]); | |||||
| break; | |||||
| } | |||||
| for(size_t slot = 0; slot < images[type].size(); slot++) { | for(size_t slot = 0; slot < images[type].size(); slot++) { | ||||
| if(!images[type][slot]) | if(!images[type][slot]) | ||||
| continue; | continue; | ||||
| if(images[type][slot]->users == 0) { | if(images[type][slot]->users == 0) { | ||||
| device_free_image(device, dscene, (ImageDataType)type, slot); | device_free_image(device, dscene, (ImageDataType)type, slot); | ||||
| } | } | ||||
| else if(images[type][slot]->need_load) { | else if(images[type][slot]->need_load) { | ||||
| ▲ Show 20 Lines • Show All 79 Lines • ▼ Show 20 Lines | void ImageManager::device_pack_images(Device *device, | ||||
| /* Byte4 Textures*/ | /* Byte4 Textures*/ | ||||
| type = IMAGE_DATA_TYPE_BYTE4; | type = IMAGE_DATA_TYPE_BYTE4; | ||||
| for(size_t slot = 0; slot < images[type].size(); slot++) { | for(size_t slot = 0; slot < images[type].size(); slot++) { | ||||
| if(!images[type][slot]) | if(!images[type][slot]) | ||||
| continue; | continue; | ||||
| device_vector<uchar4>& tex_img = dscene->tex_byte4_image[slot]; | device_vector<uchar4>& tex_img = *dscene->tex_byte4_image[slot]; | ||||
| size += tex_img.size(); | size += tex_img.size(); | ||||
| } | } | ||||
| uchar4 *pixels_byte4 = dscene->tex_image_byte4_packed.resize(size); | uchar4 *pixels_byte4 = dscene->tex_image_byte4_packed.resize(size); | ||||
| for(size_t slot = 0; slot < images[type].size(); slot++) { | for(size_t slot = 0; slot < images[type].size(); slot++) { | ||||
| if(!images[type][slot]) | if(!images[type][slot]) | ||||
| continue; | continue; | ||||
| device_vector<uchar4>& tex_img = dscene->tex_byte4_image[slot]; | device_vector<uchar4>& tex_img = *dscene->tex_byte4_image[slot]; | ||||
| uint8_t options = pack_image_options(type, slot); | uint8_t options = pack_image_options(type, slot); | ||||
| int index = type_index_to_flattened_slot(slot, type) * 2; | int index = type_index_to_flattened_slot(slot, type) * 2; | ||||
| info[index] = make_uint4(tex_img.data_width, tex_img.data_height, offset, options); | info[index] = make_uint4(tex_img.data_width, tex_img.data_height, offset, options); | ||||
| info[index+1] = make_uint4(tex_img.data_depth, 0, 0, 0); | info[index+1] = make_uint4(tex_img.data_depth, 0, 0, 0); | ||||
| memcpy(pixels_byte4+offset, (void*)tex_img.data_pointer, tex_img.memory_size()); | memcpy(pixels_byte4+offset, (void*)tex_img.data_pointer, tex_img.memory_size()); | ||||
| offset += tex_img.size(); | offset += tex_img.size(); | ||||
| } | } | ||||
| /* Float4 Textures*/ | /* Float4 Textures*/ | ||||
| type = IMAGE_DATA_TYPE_FLOAT4; | type = IMAGE_DATA_TYPE_FLOAT4; | ||||
| size = 0, offset = 0; | size = 0, offset = 0; | ||||
| for(size_t slot = 0; slot < images[type].size(); slot++) { | for(size_t slot = 0; slot < images[type].size(); slot++) { | ||||
| if(!images[type][slot]) | if(!images[type][slot]) | ||||
| continue; | continue; | ||||
| device_vector<float4>& tex_img = dscene->tex_float4_image[slot]; | device_vector<float4>& tex_img = *dscene->tex_float4_image[slot]; | ||||
| size += tex_img.size(); | size += tex_img.size(); | ||||
| } | } | ||||
| float4 *pixels_float4 = dscene->tex_image_float4_packed.resize(size); | float4 *pixels_float4 = dscene->tex_image_float4_packed.resize(size); | ||||
| for(size_t slot = 0; slot < images[type].size(); slot++) { | for(size_t slot = 0; slot < images[type].size(); slot++) { | ||||
| if(!images[type][slot]) | if(!images[type][slot]) | ||||
| continue; | continue; | ||||
| device_vector<float4>& tex_img = dscene->tex_float4_image[slot]; | device_vector<float4>& tex_img = *dscene->tex_float4_image[slot]; | ||||
| /* todo: support 3D textures, only CPU for now */ | /* todo: support 3D textures, only CPU for now */ | ||||
| uint8_t options = pack_image_options(type, slot); | uint8_t options = pack_image_options(type, slot); | ||||
| int index = type_index_to_flattened_slot(slot, type) * 2; | int index = type_index_to_flattened_slot(slot, type) * 2; | ||||
| info[index] = make_uint4(tex_img.data_width, tex_img.data_height, offset, options); | info[index] = make_uint4(tex_img.data_width, tex_img.data_height, offset, options); | ||||
| info[index+1] = make_uint4(tex_img.data_depth, 0, 0, 0); | info[index+1] = make_uint4(tex_img.data_depth, 0, 0, 0); | ||||
| memcpy(pixels_float4+offset, (void*)tex_img.data_pointer, tex_img.memory_size()); | memcpy(pixels_float4+offset, (void*)tex_img.data_pointer, tex_img.memory_size()); | ||||
| offset += tex_img.size(); | offset += tex_img.size(); | ||||
| } | } | ||||
| /* Byte Textures*/ | /* Byte Textures*/ | ||||
| type = IMAGE_DATA_TYPE_BYTE; | type = IMAGE_DATA_TYPE_BYTE; | ||||
| size = 0, offset = 0; | size = 0, offset = 0; | ||||
| for(size_t slot = 0; slot < images[type].size(); slot++) { | for(size_t slot = 0; slot < images[type].size(); slot++) { | ||||
| if(!images[type][slot]) | if(!images[type][slot]) | ||||
| continue; | continue; | ||||
| device_vector<uchar>& tex_img = dscene->tex_byte_image[slot]; | device_vector<uchar>& tex_img = *dscene->tex_byte_image[slot]; | ||||
| size += tex_img.size(); | size += tex_img.size(); | ||||
| } | } | ||||
| uchar *pixels_byte = dscene->tex_image_byte_packed.resize(size); | uchar *pixels_byte = dscene->tex_image_byte_packed.resize(size); | ||||
| for(size_t slot = 0; slot < images[type].size(); slot++) { | for(size_t slot = 0; slot < images[type].size(); slot++) { | ||||
| if(!images[type][slot]) | if(!images[type][slot]) | ||||
| continue; | continue; | ||||
| device_vector<uchar>& tex_img = dscene->tex_byte_image[slot]; | device_vector<uchar>& tex_img = *dscene->tex_byte_image[slot]; | ||||
| uint8_t options = pack_image_options(type, slot); | uint8_t options = pack_image_options(type, slot); | ||||
| int index = type_index_to_flattened_slot(slot, type) * 2; | int index = type_index_to_flattened_slot(slot, type) * 2; | ||||
| info[index] = make_uint4(tex_img.data_width, tex_img.data_height, offset, options); | info[index] = make_uint4(tex_img.data_width, tex_img.data_height, offset, options); | ||||
| info[index+1] = make_uint4(tex_img.data_depth, 0, 0, 0); | info[index+1] = make_uint4(tex_img.data_depth, 0, 0, 0); | ||||
| memcpy(pixels_byte+offset, (void*)tex_img.data_pointer, tex_img.memory_size()); | memcpy(pixels_byte+offset, (void*)tex_img.data_pointer, tex_img.memory_size()); | ||||
| offset += tex_img.size(); | offset += tex_img.size(); | ||||
| } | } | ||||
| /* Float Textures*/ | /* Float Textures*/ | ||||
| type = IMAGE_DATA_TYPE_FLOAT; | type = IMAGE_DATA_TYPE_FLOAT; | ||||
| size = 0, offset = 0; | size = 0, offset = 0; | ||||
| for(size_t slot = 0; slot < images[type].size(); slot++) { | for(size_t slot = 0; slot < images[type].size(); slot++) { | ||||
| if(!images[type][slot]) | if(!images[type][slot]) | ||||
| continue; | continue; | ||||
| device_vector<float>& tex_img = dscene->tex_float_image[slot]; | device_vector<float>& tex_img = *dscene->tex_float_image[slot]; | ||||
| size += tex_img.size(); | size += tex_img.size(); | ||||
| } | } | ||||
| float *pixels_float = dscene->tex_image_float_packed.resize(size); | float *pixels_float = dscene->tex_image_float_packed.resize(size); | ||||
| for(size_t slot = 0; slot < images[type].size(); slot++) { | for(size_t slot = 0; slot < images[type].size(); slot++) { | ||||
| if(!images[type][slot]) | if(!images[type][slot]) | ||||
| continue; | continue; | ||||
| device_vector<float>& tex_img = dscene->tex_float_image[slot]; | device_vector<float>& tex_img = *dscene->tex_float_image[slot]; | ||||
| /* todo: support 3D textures, only CPU for now */ | /* todo: support 3D textures, only CPU for now */ | ||||
| uint8_t options = pack_image_options(type, slot); | uint8_t options = pack_image_options(type, slot); | ||||
| int index = type_index_to_flattened_slot(slot, type) * 2; | int index = type_index_to_flattened_slot(slot, type) * 2; | ||||
| info[index] = make_uint4(tex_img.data_width, tex_img.data_height, offset, options); | info[index] = make_uint4(tex_img.data_width, tex_img.data_height, offset, options); | ||||
| info[index+1] = make_uint4(tex_img.data_depth, 0, 0, 0); | info[index+1] = make_uint4(tex_img.data_depth, 0, 0, 0); | ||||
| ▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | |||||
| void ImageManager::device_free(Device *device, DeviceScene *dscene) | void ImageManager::device_free(Device *device, DeviceScene *dscene) | ||||
| { | { | ||||
| for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) { | for(int type = 0; type < IMAGE_DATA_NUM_TYPES; type++) { | ||||
| for(size_t slot = 0; slot < images[type].size(); slot++) { | for(size_t slot = 0; slot < images[type].size(); slot++) { | ||||
| device_free_image(device, dscene, (ImageDataType)type, slot); | device_free_image(device, dscene, (ImageDataType)type, slot); | ||||
| } | } | ||||
| images[type].clear(); | images[type].clear(); | ||||
| } | } | ||||
| dscene->tex_byte4_image.clear(); | |||||
| dscene->tex_byte_image.clear(); | |||||
| dscene->tex_float4_image.clear(); | |||||
| dscene->tex_float_image.clear(); | |||||
| dscene->tex_half4_image.clear(); | |||||
| dscene->tex_half_image.clear(); | |||||
| device->tex_free(dscene->tex_image_byte4_packed); | device->tex_free(dscene->tex_image_byte4_packed); | ||||
| device->tex_free(dscene->tex_image_float4_packed); | device->tex_free(dscene->tex_image_float4_packed); | ||||
| device->tex_free(dscene->tex_image_byte_packed); | device->tex_free(dscene->tex_image_byte_packed); | ||||
| device->tex_free(dscene->tex_image_float_packed); | device->tex_free(dscene->tex_image_float_packed); | ||||
| device->tex_free(dscene->tex_image_packed_info); | device->tex_free(dscene->tex_image_packed_info); | ||||
| dscene->tex_image_byte4_packed.clear(); | dscene->tex_image_byte4_packed.clear(); | ||||
| dscene->tex_image_float4_packed.clear(); | dscene->tex_image_float4_packed.clear(); | ||||
| dscene->tex_image_byte_packed.clear(); | dscene->tex_image_byte_packed.clear(); | ||||
| dscene->tex_image_float_packed.clear(); | dscene->tex_image_float_packed.clear(); | ||||
| dscene->tex_image_packed_info.clear(); | dscene->tex_image_packed_info.clear(); | ||||
| } | } | ||||
| CCL_NAMESPACE_END | CCL_NAMESPACE_END | ||||
Would suggest making it a constant similar to primitive type so if we add more types we don't have to scroll over all code and replace bits.