Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/intern
diff options
context:
space:
mode:
authorGeraldine Chua <chua.gsk@gmail.com>2018-06-05 16:35:24 +0300
committerGeraldine Chua <chua.gsk@gmail.com>2018-06-05 16:35:24 +0300
commite1db45c41a9acb9dadbb40183e1037d441a15035 (patch)
tree216276fc8f6789d82d1799c80d7c59cdc6527570 /intern
parentae177e799c121f4135d2f32aa0c23cf36992afaf (diff)
Updates to tiling function.
1. Supports all data types (or at least the ones enumerated in ImageDataType). 2. Will tile all volume attributes. 3. Changed method of activating tiling to a bool member of Image.
Diffstat (limited to 'intern')
-rw-r--r--intern/cycles/blender/blender_mesh.cpp2
-rw-r--r--intern/cycles/blender/blender_session.cpp14
-rw-r--r--intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h47
-rw-r--r--intern/cycles/render/image.cpp412
-rw-r--r--intern/cycles/render/image.h24
-rw-r--r--intern/cycles/render/nodes.cpp18
-rw-r--r--intern/cycles/util/CMakeLists.txt3
-rw-r--r--intern/cycles/util/util_image_impl.h45
-rw-r--r--intern/cycles/util/util_sparse_grid.cpp174
-rw-r--r--intern/cycles/util/util_sparse_grid.h205
-rw-r--r--intern/cycles/util/util_texture.h1
11 files changed, 418 insertions, 527 deletions
diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index 7d6ca18b074..8bf3f66dff6 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -342,6 +342,7 @@ static void create_mesh_volume_attribute(BL::Object& b_ob,
ImageMetaData metadata;
bool animated = false;
bool use_alpha = true;
+ bool make_sparse = true;
volume_data->manager = image_manager;
volume_data->slot = image_manager->add_image(
@@ -352,6 +353,7 @@ static void create_mesh_volume_attribute(BL::Object& b_ob,
INTERPOLATION_LINEAR,
EXTENSION_CLIP,
use_alpha,
+ make_sparse,
metadata);
}
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index 649d6edc679..00d23b9095e 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -1051,7 +1051,6 @@ void BlenderSession::builtin_image_info(const string &builtin_name,
BL::SmokeDomainSettings b_domain = object_smoke_domain_find(b_ob);
metadata.is_float = true;
- metadata.is_volume = false;
metadata.depth = 1;
metadata.channels = 1;
@@ -1061,19 +1060,14 @@ void BlenderSession::builtin_image_info(const string &builtin_name,
if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_DENSITY) ||
builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_FLAME) ||
builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_HEAT) ||
- builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE)) {
+ builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_TEMPERATURE))
metadata.channels = 1;
- }
- else if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR)) {
+ else if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_COLOR))
metadata.channels = 4;
- metadata.is_volume = true;
- }
- else if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY)) {
+ else if(builtin_name == Attribute::standard_name(ATTR_STD_VOLUME_VELOCITY))
metadata.channels = 3;
- }
- else {
+ else
return;
- }
int3 resolution = get_int3(b_domain.domain_resolution());
int amplify = (b_domain.use_high_resolution())? b_domain.amplify() + 1: 1;
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h b/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h
index 3c18b08d5b8..3435bcab70a 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h
+++ b/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h
@@ -21,8 +21,7 @@
CCL_NAMESPACE_BEGIN
-template<typename T, bool is_tile = false>
-struct TextureInterpolator {
+template<typename T> struct TextureInterpolator {
#define SET_CUBIC_SPLINE_WEIGHTS(u, t) \
{ \
u[0] = (((-1.0f/6.0f)* t + 0.5f) * t - 0.5f) * t + (1.0f/6.0f); \
@@ -282,10 +281,13 @@ struct TextureInterpolator {
return make_float4(0.0f);
}
- if(is_tile) {
- const SparseTile *data = (const SparseTile*)info.data;
- const int *ofs = (const int*)info.offsets;
- return read(get_value(data, ofs, ix, iy, iz, width, height, depth));
+ const int *ofs = (const int*)info.offsets;
+ if(ofs) {
+ const SparseTile<T> *data = (const SparseTile<T>*)info.data;
+ return read(get_value<T>(data, ofs, ix, iy, iz,
+ compute_tile_resolution(width),
+ compute_tile_resolution(height),
+ compute_tile_resolution(depth)));
}
else {
const T *data = (const T*)info.data;
@@ -338,23 +340,26 @@ struct TextureInterpolator {
}
float4 r;
+ const int *ofs = (const int*)info.offsets;
- if(is_tile) {
- const SparseTile *data = (const SparseTile*)info.data;
- const int *ofs = (const int*)info.offsets;
+ if(ofs) {
+ const SparseTile<T> *data = (const SparseTile<T>*)info.data;
+ int tiw = compute_tile_resolution(width);
+ int tih = compute_tile_resolution(height);
+ int tid = compute_tile_resolution(depth);
/* Initial check if either voxel is in an active tile. */
- if(!is_active(ofs, ix, iy, iz, width, height, depth) &&
- !is_active(ofs, nix, niy, niz, width, height, depth)) {
+ if(!tile_is_active(ofs, ix, iy, iz, tiw, tih, tid) &&
+ !tile_is_active(ofs, nix, niy, niz, tiw, tih, tid)) {
return make_float4(0.0f);
}
- r = (1.0f - tz)*(1.0f - ty)*(1.0f - tx) * read(get_value(data, ofs, ix, iy, iz, width, height, depth));
- r += (1.0f - tz)*(1.0f - ty)*tx * read(get_value(data, ofs, nix, iy, iz, width, height, depth));
- r += (1.0f - tz)*ty*(1.0f - tx) * read(get_value(data, ofs, ix, niy, iz, width, height, depth));
- r += (1.0f - tz)*ty*tx * read(get_value(data, ofs, nix, niy, iz, width, height, depth));
- r += tz*(1.0f - ty)*(1.0f - tx) * read(get_value(data, ofs, ix, iy, niz, width, height, depth));
- r += tz*(1.0f - ty)*tx * read(get_value(data, ofs, nix, iy, niz, width, height, depth));
- r += tz*ty*(1.0f - tx) * read(get_value(data, ofs, ix, niy, niz, width, height, depth));
- r += tz*ty*tx * read(get_value(data, ofs, nix, niy, niz, width, height, depth));
+ r = (1.0f - tz)*(1.0f - ty)*(1.0f - tx) * read(get_value<T>(data, ofs, ix, iy, iz, tiw, tih, tid));
+ r += (1.0f - tz)*(1.0f - ty)*tx * read(get_value<T>(data, ofs, nix, iy, iz, tiw, tih, tid));
+ r += (1.0f - tz)*ty*(1.0f - tx) * read(get_value<T>(data, ofs, ix, niy, iz, tiw, tih, tid));
+ r += (1.0f - tz)*ty*tx * read(get_value<T>(data, ofs, nix, niy, iz, tiw, tih, tid));
+ r += tz*(1.0f - ty)*(1.0f - tx) * read(get_value<T>(data, ofs, ix, iy, niz, tiw, tih, tid));
+ r += tz*(1.0f - ty)*tx * read(get_value<T>(data, ofs, nix, iy, niz, tiw, tih, tid));
+ r += tz*ty*(1.0f - tx) * read(get_value<T>(data, ofs, ix, niy, niz, tiw, tih, tid));
+ r += tz*ty*tx * read(get_value<T>(data, ofs, nix, niy, niz, tiw, tih, tid));
}
else {
const T *data = (const T*)info.data;
@@ -384,8 +389,6 @@ struct TextureInterpolator {
#endif
float4 interp_3d_tricubic(const TextureInfo& info, float x, float y, float z)
{
- /* todo (gchua): add tile support for this */
- kernel_assert(!is_tile);
int width = info.width;
int height = info.height;
int depth = info.depth;
@@ -538,8 +541,6 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals *kg, int id, float x,
return TextureInterpolator<half4>::interp_3d(info, x, y, z, interp);
case IMAGE_DATA_TYPE_BYTE4:
return TextureInterpolator<uchar4>::interp_3d(info, x, y, z, interp);
- case IMAGE_DATA_TYPE_VOLUME:
- return TextureInterpolator<float4, true>::interp_3d(info, x, y, z, interp);
case IMAGE_DATA_TYPE_FLOAT4:
default:
return TextureInterpolator<float4>::interp_3d(info, x, y, z, interp);
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index f7e2f6488a1..c1caea34619 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -22,6 +22,7 @@
#include "util/util_logging.h"
#include "util/util_path.h"
#include "util/util_progress.h"
+#include "util/util_sparse_grid.h"
#include "util/util_texture.h"
#ifdef WITH_OSL
@@ -108,10 +109,7 @@ bool ImageManager::get_image_metadata(const string& filename,
return false;
}
- if(metadata.is_volume) {
- metadata.type = IMAGE_DATA_TYPE_VOLUME;
- }
- else if(metadata.is_float) {
+ if(metadata.is_float) {
metadata.is_linear = true;
metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_FLOAT;
}
@@ -186,10 +184,7 @@ bool ImageManager::get_image_metadata(const string& filename,
/* set type and channels */
metadata.channels = spec.nchannels;
- if(metadata.is_volume) {
- metadata.type = IMAGE_DATA_TYPE_VOLUME;
- }
- else if(metadata.is_half) {
+ if(metadata.is_half) {
metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_HALF4 : IMAGE_DATA_TYPE_HALF;
}
else if(metadata.is_float) {
@@ -241,8 +236,6 @@ string ImageManager::name_from_type(int type)
return "half4";
else if(type == IMAGE_DATA_TYPE_HALF)
return "half";
- else if(type == IMAGE_DATA_TYPE_VOLUME)
- return "volume";
else
return "byte4";
}
@@ -268,6 +261,7 @@ int ImageManager::add_image(const string& filename,
InterpolationType interpolation,
ExtensionType extension,
bool use_alpha,
+ bool make_sparse,
ImageMetaData& metadata)
{
Image *img;
@@ -345,6 +339,7 @@ int ImageManager::add_image(const string& filename,
img->extension = extension;
img->users = 1;
img->use_alpha = use_alpha;
+ img->make_sparse = make_sparse;
img->mem = NULL;
images[type][slot] = img;
@@ -582,7 +577,6 @@ bool ImageManager::file_load_image(Image *img,
* but device doesn't support single channel textures.
*/
bool is_rgba = (type == IMAGE_DATA_TYPE_FLOAT4 ||
- type == IMAGE_DATA_TYPE_VOLUME ||
type == IMAGE_DATA_TYPE_HALF4 ||
type == IMAGE_DATA_TYPE_BYTE4);
if(is_rgba) {
@@ -691,87 +685,160 @@ bool ImageManager::file_load_image(Image *img,
return true;
}
-
-/* If volume, call this to convert to sparse grid. */
-template<TypeDesc::BASETYPE FileFormat,
- typename StorageType,
+template<typename StorageType,
typename DeviceType>
-bool ImageManager::file_load_image(Image *img,
- ImageDataType type,
- int texture_limit,
- device_vector<SparseTile>& tex_img,
- device_vector<int>& tex_offsets)
+void ImageManager::file_load_failed(device_vector<DeviceType> *tex_img,
+ ImageDataType type)
{
+ /* On failure to load, we set a 1x1 pixels pink image. */
+ thread_scoped_lock device_lock(device_mutex);
+ StorageType *pixels = (StorageType*)tex_img->alloc(1, 1);
- device_vector<DeviceType> *tex_img_dense
- = new device_vector<DeviceType>(NULL, img->mem_name.c_str(), MEM_TEXTURE);
-
- if(!file_load_image<FileFormat, StorageType, DeviceType>(img,
- type,
- texture_limit,
- *tex_img_dense))
- {
- /* Release temporary pointer. */
- delete tex_img_dense;
- tex_img_dense = NULL;
- return false;
+ switch(type) {
+ case IMAGE_DATA_TYPE_FLOAT4:
+ pixels[0] = TEX_IMAGE_MISSING_R;
+ pixels[1] = TEX_IMAGE_MISSING_G;
+ pixels[2] = TEX_IMAGE_MISSING_B;
+ pixels[3] = TEX_IMAGE_MISSING_A;
+ break;
+ case IMAGE_DATA_TYPE_FLOAT:
+ pixels[0] = TEX_IMAGE_MISSING_R;
+ break;
+ case IMAGE_DATA_TYPE_BYTE4:
+ pixels[0] = (TEX_IMAGE_MISSING_R * 255);
+ pixels[1] = (TEX_IMAGE_MISSING_G * 255);
+ pixels[2] = (TEX_IMAGE_MISSING_B * 255);
+ pixels[3] = (TEX_IMAGE_MISSING_A * 255);
+ break;
+ case IMAGE_DATA_TYPE_BYTE:
+ pixels[0] = (TEX_IMAGE_MISSING_R * 255);
+ break;
+ case IMAGE_DATA_TYPE_HALF4:
+ pixels[0] = TEX_IMAGE_MISSING_R;
+ pixels[1] = TEX_IMAGE_MISSING_G;
+ pixels[2] = TEX_IMAGE_MISSING_B;
+ pixels[3] = TEX_IMAGE_MISSING_A;
+ break;
+ case IMAGE_DATA_TYPE_HALF:
+ pixels[0] = TEX_IMAGE_MISSING_R;
+ break;
+ default:
+ assert(0);
}
+}
- DeviceType *data = tex_img_dense->data();
- size_t tile_width = compute_tile_resolution(tex_img_dense->data_width);
- size_t tile_height = compute_tile_resolution(tex_img_dense->data_height);
- size_t tile_depth = compute_tile_resolution(tex_img_dense->data_depth);
-
- vector<SparseTile> sparse_grid;
+template<typename DeviceType>
+bool ImageManager::file_make_image_sparse(Device *device,
+ Image *img,
+ device_vector<DeviceType> *tex_dense)
+{
+ device_vector<SparseTile<DeviceType>> *tex_sparse
+ = new device_vector<SparseTile<DeviceType>>(device,
+ (img->mem_name).c_str(),
+ MEM_TEXTURE);
+ device_vector<int> *tex_offsets
+ = new device_vector<int>(device,
+ (img->mem_name + "_offsets").c_str(),
+ MEM_TEXTURE);
+
+ vector<SparseTile<DeviceType>> sparse_grid;
vector<int> offsets;
- /* Sample threshold value for now. */
- float4 threshold = make_float4(0.0f);
- int active_tile_count = create_sparse_grid(data, threshold,
- tex_img_dense->data_width,
- tex_img_dense->data_height,
- tex_img_dense->data_depth,
- &sparse_grid, &offsets);
+ int active_tile_count = create_sparse_grid<DeviceType>(
+ tex_dense->data(),
+ tex_dense->data_width,
+ tex_dense->data_height,
+ tex_dense->data_depth,
+ &sparse_grid,
+ &offsets);
if(active_tile_count < 1) {
- /* to-do (gchua): handle this. */
+ VLOG(1) << "Could not make sparse grid for "
+ << path_filename(img->filename) << " (" << img->mem_name << ")"
+ << ", no active tiles";
+ delete tex_sparse;
+ delete tex_offsets;
+ tex_sparse = NULL;
+ tex_offsets = NULL;
+ return false;
}
- SparseTile *texture_pixels;
+ SparseTile<DeviceType> *texture_pixels;
int *texture_offsets;
+ int tiw = compute_tile_resolution(tex_dense->data_width);
+ int tih = compute_tile_resolution(tex_dense->data_height);
+ int tid = compute_tile_resolution(tex_dense->data_depth);
+
{
- /* Since only active tiles are stored in tex_img, its
+ /* Since only active tiles are stored in tex_sparse, its
* allocated memory will be <= the actual resolution
* of the volume. We store the true resolution (in tiles) in the
* tex_offsets instead, since it needs to be allocated enough
* space to track all tiles anyway. */
thread_scoped_lock device_lock(device_mutex);
- texture_pixels = (SparseTile*)tex_img.alloc(active_tile_count);
- texture_offsets = (int*)tex_offsets.alloc(tile_width,
- tile_height,
- tile_depth);
+ texture_pixels = (SparseTile<DeviceType>*)tex_sparse->alloc(active_tile_count);
+ texture_offsets = (int*)tex_offsets->alloc(tiw, tih, tid);
}
- memcpy(texture_offsets,
+ memcpy(&texture_offsets[0],
&offsets[0],
offsets.size() * sizeof(int));
- memcpy(texture_pixels,
+ memcpy(&texture_pixels[0],
&sparse_grid[0],
- active_tile_count * sizeof(SparseTile));
+ active_tile_count * sizeof(SparseTile<DeviceType>));
- VLOG(1) << "Memory usage of dense grid '" << img->filename << "': "
- << string_human_readable_size(tex_img_dense->memory_size());
- VLOG(1) << "Memory usage of sparse grid '" << img->filename << "': "
- << string_human_readable_size(tex_img.memory_size());
- VLOG(1) << "Memory usage of auxiliary index: "
- << string_human_readable_size(tex_offsets.memory_size());
+ img->mem = tex_sparse;
+ img->mem->interpolation = img->interpolation;
+ img->mem->extension = img->extension;
+ img->mem->offsets = tex_offsets;
- /* Release temporary pointer. */
- delete tex_img_dense;
- tex_img_dense = NULL;
+ thread_scoped_lock device_lock(device_mutex);
+ tex_sparse->copy_to_device();
+
+ VLOG(1) << "Original memory usage of '"
+ << path_filename(img->filename) << "' (" << img->mem_name << "): "
+ << string_human_readable_size(tex_dense->memory_size());
return true;
}
+template<TypeDesc::BASETYPE FileFormat,
+ typename StorageType,
+ typename DeviceType>
+void ImageManager::load_image(Device *device,
+ Image *img,
+ ImageDataType type,
+ int texture_limit)
+{
+ device_vector<DeviceType> *tex_img
+ = new device_vector<DeviceType>(device,
+ img->mem_name.c_str(),
+ MEM_TEXTURE);
+
+ if(!file_load_image<FileFormat, StorageType, DeviceType>(img,
+ type,
+ texture_limit,
+ *tex_img)) {
+ VLOG(1) << "Failed to load "
+ << path_filename(img->filename) << " (" << img->mem_name << ")";
+ file_load_failed<StorageType, DeviceType>(tex_img, type);
+ }
+
+ if(img->make_sparse) {
+ if(file_make_image_sparse<DeviceType>(device, img, tex_img)) {
+ delete tex_img;
+ tex_img = NULL;
+ }
+ }
+
+ if(tex_img) {
+ img->mem = tex_img;
+ img->mem->interpolation = img->interpolation;
+ img->mem->extension = img->extension;
+ thread_scoped_lock device_lock(device_mutex);
+ tex_img->copy_to_device();
+ }
+}
+
void ImageManager::device_load_image(Device *device,
Scene *scene,
ImageDataType type,
@@ -807,198 +874,27 @@ void ImageManager::device_load_image(Device *device,
}
/* Create new texture. */
- if(type == IMAGE_DATA_TYPE_FLOAT4) {
- device_vector<float4> *tex_img
- = new device_vector<float4>(device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if(!file_load_image<TypeDesc::FLOAT, float>(img,
- type,
- texture_limit,
- *tex_img))
- {
- /* on failure to load, we set a 1x1 pixels pink image */
- thread_scoped_lock device_lock(device_mutex);
- float *pixels = (float*)tex_img->alloc(1, 1);
-
- pixels[0] = TEX_IMAGE_MISSING_R;
- pixels[1] = TEX_IMAGE_MISSING_G;
- pixels[2] = TEX_IMAGE_MISSING_B;
- pixels[3] = TEX_IMAGE_MISSING_A;
- }
-
- img->mem = tex_img;
- img->mem->interpolation = img->interpolation;
- img->mem->extension = img->extension;
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
- }
- else if(type == IMAGE_DATA_TYPE_FLOAT) {
- device_vector<float> *tex_img
- = new device_vector<float>(device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if(!file_load_image<TypeDesc::FLOAT, float>(img,
- type,
- texture_limit,
- *tex_img))
- {
- /* on failure to load, we set a 1x1 pixels pink image */
- thread_scoped_lock device_lock(device_mutex);
- float *pixels = (float*)tex_img->alloc(1, 1);
-
- pixels[0] = TEX_IMAGE_MISSING_R;
- }
-
- img->mem = tex_img;
- img->mem->interpolation = img->interpolation;
- img->mem->extension = img->extension;
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
- }
- else if(type == IMAGE_DATA_TYPE_BYTE4) {
- device_vector<uchar4> *tex_img
- = new device_vector<uchar4>(device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if(!file_load_image<TypeDesc::UINT8, uchar>(img,
- type,
- texture_limit,
- *tex_img))
- {
- /* on failure to load, we set a 1x1 pixels pink image */
- thread_scoped_lock device_lock(device_mutex);
- uchar *pixels = (uchar*)tex_img->alloc(1, 1);
-
- pixels[0] = (TEX_IMAGE_MISSING_R * 255);
- pixels[1] = (TEX_IMAGE_MISSING_G * 255);
- pixels[2] = (TEX_IMAGE_MISSING_B * 255);
- pixels[3] = (TEX_IMAGE_MISSING_A * 255);
- }
-
- img->mem = tex_img;
- img->mem->interpolation = img->interpolation;
- img->mem->extension = img->extension;
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
- }
- else if(type == IMAGE_DATA_TYPE_BYTE) {
- device_vector<uchar> *tex_img
- = new device_vector<uchar>(device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if(!file_load_image<TypeDesc::UINT8, uchar>(img,
- type,
- texture_limit,
- *tex_img)) {
- /* on failure to load, we set a 1x1 pixels pink image */
- thread_scoped_lock device_lock(device_mutex);
- uchar *pixels = (uchar*)tex_img->alloc(1, 1);
-
- pixels[0] = (TEX_IMAGE_MISSING_R * 255);
- }
-
- img->mem = tex_img;
- img->mem->interpolation = img->interpolation;
- img->mem->extension = img->extension;
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
- }
- else if(type == IMAGE_DATA_TYPE_HALF4) {
- device_vector<half4> *tex_img
- = new device_vector<half4>(device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if(!file_load_image<TypeDesc::HALF, half>(img,
- type,
- texture_limit,
- *tex_img)) {
- /* on failure to load, we set a 1x1 pixels pink image */
- thread_scoped_lock device_lock(device_mutex);
- half *pixels = (half*)tex_img->alloc(1, 1);
-
- pixels[0] = TEX_IMAGE_MISSING_R;
- pixels[1] = TEX_IMAGE_MISSING_G;
- pixels[2] = TEX_IMAGE_MISSING_B;
- pixels[3] = TEX_IMAGE_MISSING_A;
- }
-
- img->mem = tex_img;
- img->mem->interpolation = img->interpolation;
- img->mem->extension = img->extension;
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
- }
- else if(type == IMAGE_DATA_TYPE_HALF) {
- device_vector<half> *tex_img
- = new device_vector<half>(device, img->mem_name.c_str(), MEM_TEXTURE);
-
- if(!file_load_image<TypeDesc::HALF, half>(img,
- type,
- texture_limit,
- *tex_img)) {
- /* on failure to load, we set a 1x1 pixels pink image */
- thread_scoped_lock device_lock(device_mutex);
- half *pixels = (half*)tex_img->alloc(1, 1);
-
- pixels[0] = TEX_IMAGE_MISSING_R;
- }
-
- img->mem = tex_img;
- img->mem->interpolation = img->interpolation;
- img->mem->extension = img->extension;
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
- }
- else if(type == IMAGE_DATA_TYPE_VOLUME) {
- device_vector<SparseTile> *tex_img
- = new device_vector<SparseTile>(device, img->mem_name.c_str(), MEM_TEXTURE);
- device_vector<int> *tex_offsets
- = new device_vector<int>(device, (img->mem_name + "_offsets").c_str(), MEM_TEXTURE);
-
- if(!file_load_image<TypeDesc::FLOAT, float, float4>(img,
- type,
- texture_limit,
- *tex_img,
- *tex_offsets))
- {
- /* Clear pointers. */
- delete tex_img;
- delete tex_offsets;
- tex_img = NULL;
- tex_offsets = NULL;
-
- /* on failure to load, we set a 1x1 pixels pink image (float4) */
- device_vector<float4> *tex_fail
- = new device_vector<float4>(device, img->mem_name.c_str(), MEM_TEXTURE);
-
- thread_scoped_lock device_lock(device_mutex);
- float *pixels = (float*)tex_fail->alloc(1, 1);
-
- pixels[0] = TEX_IMAGE_MISSING_R;
- pixels[1] = TEX_IMAGE_MISSING_G;
- pixels[2] = TEX_IMAGE_MISSING_B;
- pixels[3] = TEX_IMAGE_MISSING_A;
-
- img->mem = tex_fail;
- img->mem->interpolation = img->interpolation;
- img->mem->extension = img->extension;
- tex_fail->copy_to_device();
- }
- else {
- img->mem = tex_img;
- img->mem->interpolation = img->interpolation;
- img->mem->extension = img->extension;
- img->mem->offets = tex_offsets;
- /* Need to set interpolation so that tex_alloc() will treat
- * tex_offsets as a image instead of data texture. */
- tex_offsets->interpolation = img->interpolation;
-
- thread_scoped_lock device_lock(device_mutex);
- tex_img->copy_to_device();
- tex_offsets->copy_to_device();
- }
+ switch(type) {
+ case IMAGE_DATA_TYPE_FLOAT4:
+ load_image<TypeDesc::FLOAT, float, float4>(device, img, type, texture_limit);
+ break;
+ case IMAGE_DATA_TYPE_FLOAT:
+ load_image<TypeDesc::FLOAT, float, float>(device, img, type, texture_limit);
+ break;
+ case IMAGE_DATA_TYPE_BYTE4:
+ load_image<TypeDesc::UINT8, uchar, uchar4>(device, img, type, texture_limit);
+ break;
+ case IMAGE_DATA_TYPE_BYTE:
+ load_image<TypeDesc::UINT8, uchar, uchar>(device, img, type, texture_limit);
+ break;
+ case IMAGE_DATA_TYPE_HALF4:
+ load_image<TypeDesc::HALF, half, half4>(device, img, type, texture_limit);
+ break;
+ case IMAGE_DATA_TYPE_HALF:
+ load_image<TypeDesc::HALF, half, half>(device, img, type, texture_limit);
+ break;
+ default:
+ assert(0);
}
img->need_load = false;
@@ -1007,6 +903,7 @@ void ImageManager::device_load_image(Device *device,
void ImageManager::device_free_image(Device *, ImageDataType type, int slot)
{
Image *img = images[type][slot];
+ VLOG(1) << "Freeing " << img->mem_name;
if(img) {
if(osl_texture_system && !img->builtin_data) {
@@ -1018,6 +915,9 @@ void ImageManager::device_free_image(Device *, ImageDataType type, int slot)
if(img->mem) {
thread_scoped_lock device_lock(device_mutex);
+ if(img->mem->offsets){
+ delete img->mem->offsets;
+ }
delete img->mem;
}
diff --git a/intern/cycles/render/image.h b/intern/cycles/render/image.h
index 0b493110076..7ef9cfb5ba5 100644
--- a/intern/cycles/render/image.h
+++ b/intern/cycles/render/image.h
@@ -24,7 +24,6 @@
#include "util/util_string.h"
#include "util/util_thread.h"
#include "util/util_vector.h"
-#include "util/util_sparse_grid.h"
CCL_NAMESPACE_BEGIN
@@ -35,7 +34,7 @@ class Scene;
class ImageMetaData {
public:
/* Must be set by image file or builtin callback. */
- bool is_float, is_half, is_volume;
+ bool is_float, is_half;
int channels;
size_t width, height, depth;
bool builtin_free_cache;
@@ -57,6 +56,7 @@ public:
InterpolationType interpolation,
ExtensionType extension,
bool use_alpha,
+ bool make_sparse,
ImageMetaData& metadata);
void remove_image(int flat_slot);
void remove_image(const string& filename,
@@ -116,6 +116,7 @@ public:
bool use_alpha;
bool need_load;
bool animated;
+ bool make_sparse;
float frame;
InterpolationType interpolation;
ExtensionType extension;
@@ -152,14 +153,23 @@ private:
int texture_limit,
device_vector<DeviceType>& tex_img);
+ template<typename StorageType,
+ typename DeviceType>
+ void file_load_failed(device_vector<DeviceType> *tex_img,
+ ImageDataType type);
+
+ template<typename DeviceType>
+ bool file_make_image_sparse(Device *device,
+ Image *img,
+ device_vector<DeviceType> *tex_dense);
+
template<TypeDesc::BASETYPE FileFormat,
typename StorageType,
typename DeviceType>
- bool file_load_image(Image *img,
- ImageDataType type,
- int texture_limit,
- device_vector<SparseTile>& tex_img,
- device_vector<int>& tex_offsets);
+ void load_image(Device *device,
+ Image *img,
+ ImageDataType type,
+ int texture_limit);
int max_flattened_slot(ImageDataType type);
int type_index_to_flattened_slot(int slot, ImageDataType type);
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 3dad4d1a346..71b1d42b25e 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -307,6 +307,7 @@ void ImageTextureNode::compile(SVMCompiler& compiler)
interpolation,
extension,
use_alpha,
+ false,
metadata);
is_float = metadata.is_float;
is_linear = metadata.is_linear;
@@ -372,6 +373,7 @@ void ImageTextureNode::compile(OSLCompiler& compiler)
interpolation,
extension,
use_alpha,
+ false,
metadata);
}
is_float = metadata.is_float;
@@ -502,6 +504,7 @@ void EnvironmentTextureNode::compile(SVMCompiler& compiler)
interpolation,
EXTENSION_REPEAT,
use_alpha,
+ false,
metadata);
is_float = metadata.is_float;
is_linear = metadata.is_linear;
@@ -558,6 +561,7 @@ void EnvironmentTextureNode::compile(OSLCompiler& compiler)
interpolation,
EXTENSION_REPEAT,
use_alpha,
+ false,
metadata);
}
is_float = metadata.is_float;
@@ -1502,11 +1506,14 @@ void PointDensityTextureNode::compile(SVMCompiler& compiler)
if(use_density || use_color) {
if(slot == -1) {
ImageMetaData metadata;
- slot = image_manager->add_image(filename.string(), builtin_data,
- false, 0,
+ slot = image_manager->add_image(filename.string(),
+ builtin_data,
+ false,
+ 0,
interpolation,
EXTENSION_CLIP,
true,
+ false,
metadata);
}
@@ -1553,11 +1560,14 @@ void PointDensityTextureNode::compile(OSLCompiler& compiler)
if(use_density || use_color) {
if(slot == -1) {
ImageMetaData metadata;
- slot = image_manager->add_image(filename.string(), builtin_data,
- false, 0,
+ slot = image_manager->add_image(filename.string(),
+ builtin_data,
+ false,
+ 0,
interpolation,
EXTENSION_CLIP,
true,
+ false,
metadata);
}
diff --git a/intern/cycles/util/CMakeLists.txt b/intern/cycles/util/CMakeLists.txt
index 940e9d0441e..005b1d41dc2 100644
--- a/intern/cycles/util/CMakeLists.txt
+++ b/intern/cycles/util/CMakeLists.txt
@@ -18,7 +18,6 @@ set(SRC
util_path.cpp
util_string.cpp
util_simd.cpp
- util_sparse_grid.cpp
util_system.cpp
util_task.cpp
util_thread.cpp
@@ -79,7 +78,7 @@ set(SRC_HEADERS
util_sky_model.h
util_sky_model_data.h
util_avxf.h
- util_sparse_grid.cpp
+ util_sparse_grid.h
util_sseb.h
util_ssef.h
util_ssei.h
diff --git a/intern/cycles/util/util_image_impl.h b/intern/cycles/util/util_image_impl.h
index 751f52aaa86..c60588dcedb 100644
--- a/intern/cycles/util/util_image_impl.h
+++ b/intern/cycles/util/util_image_impl.h
@@ -23,21 +23,6 @@
CCL_NAMESPACE_BEGIN
-namespace {
-
-template<typename T>
-const T *util_image_read(const vector<T>& pixels,
- const size_t width,
- const size_t height,
- const size_t /*depth*/,
- const size_t components,
- const size_t x, const size_t y, const size_t z) {
- const size_t index = ((size_t)z * (width * height) +
- (size_t)y * width +
- (size_t)x) * components;
- return &pixels[index];
-}
-
/* Cast input pixel from unknown storage to float. */
template<typename T>
inline float cast_to_float(T value);
@@ -83,6 +68,36 @@ inline half cast_from_float(float value)
{
return float_to_half(value);
}
+template<>
+inline float4 cast_from_float(float value)
+{
+ return make_float4(value);
+}
+template<>
+inline uchar4 cast_from_float(float value)
+{
+ return make_uchar4(cast_from_float<uchar>(value));
+}
+template<>
+inline half4 cast_from_float(float value)
+{
+ return make_half4(cast_from_float<half>(value));
+}
+
+namespace {
+
+template<typename T>
+const T *util_image_read(const vector<T>& pixels,
+ const size_t width,
+ const size_t height,
+ const size_t /*depth*/,
+ const size_t components,
+ const size_t x, const size_t y, const size_t z) {
+ const size_t index = ((size_t)z * (width * height) +
+ (size_t)y * width +
+ (size_t)x) * components;
+ return &pixels[index];
+}
template<typename T>
void util_image_downscale_sample(const vector<T>& pixels,
diff --git a/intern/cycles/util/util_sparse_grid.cpp b/intern/cycles/util/util_sparse_grid.cpp
deleted file mode 100644
index e5ae32b3f78..00000000000
--- a/intern/cycles/util/util_sparse_grid.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright 2011-2018 Blender Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "util/util_sparse_grid.h"
-#include "util/util_math.h"
-
-/* Functions to help generate and handle Sparse Grids. */
-
-CCL_NAMESPACE_BEGIN
-
-int compute_index(int x, int y, int z, int width, int height, int depth, int min)
-{
- if(x < min || y < min || z < min || x >= width || y >= height || z >= depth) {
- return min-1;
- }
- return x + width * (y + z * height);
-}
-
-int3 compute_coordinates(int index, int width, int height, int depth, int min)
-{
- if(index < min || index >= width * height * depth) {
- return make_int3(min-1, min-1, min-1);
- }
- int x = index % width;
- int y = (index / width) % height;
- int z = index / (width * height);
- return make_int3(x, y, z);
-}
-
-int compute_tile_resolution(int res)
-{
- if(res % TILE_SIZE == 0) {
- return res / TILE_SIZE;
- }
- return res / TILE_SIZE + 1;
-}
-
-bool is_active(const int *offsets,
- size_t x, size_t y, size_t z,
- size_t width, size_t height, size_t depth)
-{
- if(offsets == NULL)
- return false;
- int tile_width = compute_tile_resolution(width);
- int tile_height = compute_tile_resolution(height);
- int tile_depth = compute_tile_resolution(depth);
- int tile_index = compute_index(x/TILE_SIZE, y/TILE_SIZE, z/TILE_SIZE,
- tile_width, tile_height, tile_depth);
- if(tile_index < 0 || tile_index > tile_width*tile_height*tile_depth)
- return false;
- int grid_index = offsets[tile_index];
- return (grid_index >= 0 && grid_index < width*height*depth);
-}
-
-float4 get_value(const SparseTile *grid, const int *offsets,
- size_t x, size_t y, size_t z,
- size_t width, size_t height, size_t depth)
-{
- if(offsets == NULL) {
- return make_float4(0.0f);
- }
- int tile_width = compute_tile_resolution(width);
- int tile_height = compute_tile_resolution(height);
- int tile_depth = compute_tile_resolution(depth);
- /* Get the 1D array tile index of the tile the voxel (x, y, z) is in. */
- int tile_index = compute_index(x/TILE_SIZE, y/TILE_SIZE, z/TILE_SIZE,
- tile_width, tile_height, tile_depth);
- if(tile_index < 0 || tile_index > tile_width*tile_height*tile_depth) {
- return make_float4(0.0f);
- }
- /* Get the index of the tile in the sparse grid. */
- int grid_index = offsets[tile_index];
- if (grid_index < 0 || grid_index > width*height*depth) {
- return make_float4(0.0f);
- }
- /* Get tile and look up voxel in tile. */
- int voxel_index = compute_index(x%TILE_SIZE, y%TILE_SIZE, z%TILE_SIZE);
- return grid[grid_index].values[voxel_index];
-}
-
-float4 get_value(const SparseTile *grid, const int *offsets,
- size_t tile_index,
- size_t width, size_t height, size_t depth)
-{
- int3 c = compute_coordinates(tile_index, width, height, depth);
- return get_value(grid, offsets, c.x, c.y, c.z, width, height, depth);
-}
-
-int create_sparse_grid(float4 *dense_grid,
- const size_t width,
- const size_t height,
- const size_t depth,
- vector<SparseTile> *sparse_grid,
- vector<int> *offsets)
-{
-
- /* Resize vectors to tiled resolution. */
- int active_tile_count = 0;
- int total_tile_count = compute_tile_resolution(width) *
- compute_tile_resolution(height) *
- compute_tile_resolution(depth);
- /* Overalloc grid because we don't know the
- * number of active tiles yet. */
- sparse_grid->resize(total_tile_count);
- offsets->resize(total_tile_count);
- total_tile_count = 0;
-
- for(int z=0 ; z < depth ; z += TILE_SIZE) {
- for(int y=0 ; y < height ; y += TILE_SIZE) {
- for(int x=0 ; x < width ; x += TILE_SIZE) {
-
- SparseTile tile;
- bool is_empty = true;
- int c = 0;
-
- /* Populate the tile. */
- for(int k=z ; k < z+TILE_SIZE ; ++k) {
- for(int j=y ; j < y+TILE_SIZE ; ++j) {
- for(int i=x ; i < x+TILE_SIZE ; ++i) {
- int index = compute_index(i, j, k, width, height, depth);
- if(index < 0) {
- /* Out of bounds of original image, store an empty voxel. */
- tile.values[c] = make_float4(0.0f);
- }
- else {
- tile.values[c] = dense_grid[index];
- if(is_empty) {
- if(dense_grid[index].x > 0.0f ||
- dense_grid[index].y > 0.0f ||
- dense_grid[index].z > 0.0f ||
- dense_grid[index].w > 0.0f) {
- /* All values are greater than the threshold. */
- is_empty = false;
- }
- }
- }
- ++c;
- }
- }
- }
-
- /* Add tile if active. */
- if(is_empty) {
- (*offsets)[total_tile_count] = -1;
- }
- else {
- (*sparse_grid)[active_tile_count] = tile;
- (*offsets)[total_tile_count] = active_tile_count;
- ++active_tile_count;
- }
- ++total_tile_count;
- }
- }
- }
-
- /* Return so that the parent function can resize
- * sparse_grid appropriately. */
- return active_tile_count;
-}
-
-CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_sparse_grid.h b/intern/cycles/util/util_sparse_grid.h
index cf94dcd62b1..910d4f4e1fb 100644
--- a/intern/cycles/util/util_sparse_grid.h
+++ b/intern/cycles/util/util_sparse_grid.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2011-2017 Blender Foundation
+ * Copyright 2011-2018 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,49 +17,184 @@
#ifndef __UTIL_SPARSE_GRID_H__
#define __UTIL_SPARSE_GRID_H__
+#include "util/util_half.h"
+#include "util/util_image.h"
#include "util/util_types.h"
#include "util/util_vector.h"
+/* Functions to help generate and handle Sparse Grids.
+ *
+ * In this file, we use two different indexing systems:
+ * in terms of voxels and in terms of tiles.
+ *
+ * The compute_*() functions work with either system,
+ * so long as all args are in the same format.
+ *
+ * For all other functions:
+ * - x, y, z, width, height, depth are measured by voxels.
+ * - tix, tiy, tiz, tiw, tih, tid are measured by tiles.
+ *
+ */
+
CCL_NAMESPACE_BEGIN
+/* For some type4 textures (e.g. color), they may still be
+ * considered active even if at least one of their values
+ * is beneath the threshold. Thus, we require a custom
+ * function using ORs instead of ANDs.
+ */
+namespace {
+ inline bool gt(float a, float b) { return a > b; }
+ inline bool gt(uchar a, uchar b) { return a > b; }
+ inline bool gt(half a, half b) { return a > b; }
+ inline bool gt(float4 a, float4 b) { return a.x > b.x || a.y > b.y || a.z > b.z || a.w > b.w; }
+ inline bool gt(uchar4 a, uchar4 b) { return a.x > b.x || a.y > b.y || a.z > b.z || a.w > b.w; }
+ inline bool gt(half4 a, half4 b) { return a.x > b.x || a.y > b.y || a.z > b.z || a.w > b.w; }
+}
+
static const int TILE_SIZE = 8;
+static const float THRESHOLD = 0.001f;
-struct SparseTile {
- float4 values[TILE_SIZE * TILE_SIZE * TILE_SIZE];
+template<typename T> struct SparseTile {
+ T values[TILE_SIZE * TILE_SIZE * TILE_SIZE];
};
-int compute_index(int x, int y, int z,
- int width=TILE_SIZE,
- int height=TILE_SIZE,
- int depth=TILE_SIZE,
- int min=0);
-
-int3 compute_coordinates(int index,
- int width=TILE_SIZE,
- int height=TILE_SIZE,
- int depth=TILE_SIZE,
- int min=0);
-
-int compute_tile_resolution(int res);
-
-bool is_active(const int *offsets,
- size_t x, size_t y, size_t z,
- size_t width, size_t height, size_t depth);
-
-int create_sparse_grid(float4 *dense_grid,
- const size_t width,
- const size_t height,
- const size_t depth,
- vector<SparseTile> *sparse_grid,
- vector<int> *offsets);
-
-float4 get_value(const SparseTile *grid, const int *offsets,
- size_t x, size_t y, size_t z,
- size_t width, size_t height, size_t depth);
-
-float4 get_value(const SparseTile *grid, const int *offsets,
- size_t tile_index,
- size_t width, size_t height, size_t depth);
+const inline int compute_index(const size_t x, const size_t y, const size_t z,
+ const size_t width, const size_t height, const size_t depth)
+{
+ if(x >= width || y >= height || z >= depth) {
+ return -1;
+ }
+ return x + width * (y + z * height);
+}
+
+const inline int3 compute_coordinates(const size_t index, const size_t width,
+ const size_t height, const size_t depth)
+{
+ if(index >= width * height * depth) {
+ return make_int3(-1, -1, -1);
+ }
+ int x = index % width;
+ int y = (index / width) % height;
+ int z = index / (width * height);
+ return make_int3(x, y, z);
+}
+
+const inline size_t compute_tile_resolution(const size_t res)
+{
+ return (res / TILE_SIZE) + !(res % TILE_SIZE == 0);
+}
+
+/* Sampling functions accept lookup coordinates in voxel format
+ * and image resolution in tile format. This is because most
+ * algorithms will sample one image multiple times, so it is
+ * more efficient for the parent function itself to convert the
+ * resolution to the tiled system only once.
+ */
+
+const inline bool tile_is_active(const int *offsets,
+ int x, int y, int z,
+ int tiw, int tih, int tid)
+{
+ int tix = x/TILE_SIZE, tiy = y/TILE_SIZE, tiz = z/TILE_SIZE;
+ int dense_index = compute_index(tix, tiy, tiz, tiw, tih, tid);
+ return dense_index < 0 ? false : offsets[dense_index] >= 0;
+}
+
+template<typename T>
+const T get_value(const SparseTile<T> *grid, const int *offsets,
+ int x, int y, int z, int tiw, int tih, int tid)
+{
+ /* Get the 1D array index in the dense grid of the tile (x, y, z) is in. */
+ int tix = x/TILE_SIZE, tiy = y/TILE_SIZE, tiz = z/TILE_SIZE;
+ int dense_index = compute_index(tix, tiy, tiz, tiw, tih, tid);
+ if(dense_index < 0) {
+ return cast_from_float<T>(0.0f);
+ }
+ /* Get the index of the tile in the sparse grid. */
+ int sparse_index = offsets[dense_index];
+ if (sparse_index < 0) {
+ return cast_from_float<T>(0.0f);
+ }
+ /* Look up voxel in the tile. */
+ int in_tile_index = compute_index(x%TILE_SIZE, y%TILE_SIZE, z%TILE_SIZE,
+ TILE_SIZE, TILE_SIZE, TILE_SIZE);
+ return grid[sparse_index].values[in_tile_index];
+}
+
+template<typename T>
+int create_sparse_grid(const T *dense_grid,
+ int width, int height, int depth,
+ vector<SparseTile<T>> *sparse_grid,
+ vector<int> *offsets)
+{
+ if(!dense_grid) {
+ return 0;
+ }
+
+ const T empty = cast_from_float<T>(0.0f);
+ const T threshold = cast_from_float<T>(THRESHOLD);
+ int active_tile_count = 0;
+ int total_tile_count = compute_tile_resolution(width) *
+ compute_tile_resolution(height) *
+ compute_tile_resolution(depth);
+
+ /* Resize vectors to tiled resolution. Have to overalloc
+ * sparse_grid because we don't know the number of
+ * active tiles yet. */
+ sparse_grid->resize(total_tile_count);
+ offsets->resize(total_tile_count);
+ total_tile_count = 0;
+
+ for(int z=0 ; z < depth ; z += TILE_SIZE) {
+ for(int y=0 ; y < height ; y += TILE_SIZE) {
+ for(int x=0 ; x < width ; x += TILE_SIZE) {
+
+ SparseTile<T> tile;
+ bool tile_is_empty = true;
+ int c = 0;
+
+ /* Populate the tile. */
+ for(int k=z ; k < z+TILE_SIZE ; ++k) {
+ for(int j=y ; j < y+TILE_SIZE ; ++j) {
+ for(int i=x ; i < x+TILE_SIZE ; ++i) {
+ int index = compute_index(i, j, k, width, height, depth);
+ if(index < 0) {
+ /* Out of bounds of original image
+ * store an empty voxel. */
+ tile.values[c] = empty;
+ }
+ else {
+ tile.values[c] = dense_grid[index];
+ if(tile_is_empty) {
+ if(gt(dense_grid[index], threshold)) {
+ tile_is_empty = false;
+ }
+ }
+ }
+ ++c;
+ }
+ }
+ }
+
+ /* Add tile if active. */
+ if(tile_is_empty) {
+ (*offsets)[total_tile_count] = -1;
+ }
+ else {
+ (*sparse_grid)[active_tile_count] = tile;
+ (*offsets)[total_tile_count] = active_tile_count;
+ ++active_tile_count;
+ }
+ ++total_tile_count;
+ }
+ }
+ }
+
+ /* Return so that the parent function can resize
+ * sparse_grid appropriately. */
+ return active_tile_count;
+}
CCL_NAMESPACE_END
diff --git a/intern/cycles/util/util_texture.h b/intern/cycles/util/util_texture.h
index a747d783009..a571afcd9a2 100644
--- a/intern/cycles/util/util_texture.h
+++ b/intern/cycles/util/util_texture.h
@@ -53,7 +53,6 @@ typedef enum ImageDataType {
IMAGE_DATA_TYPE_FLOAT = 3,
IMAGE_DATA_TYPE_BYTE = 4,
IMAGE_DATA_TYPE_HALF = 5,
- IMAGE_DATA_TYPE_VOLUME = 6,
IMAGE_DATA_NUM_TYPES
} ImageDataType;