[Bf-blender-cvs] [6311a9f] master: Cycles: Support half and half4 textures.

Thomas Dinges noreply at git.blender.org
Sun Jun 19 17:34:39 CEST 2016


Commit: 6311a9ff234aecb054121bf12ad03da6242fc092
Author: Thomas Dinges
Date:   Sun Jun 19 17:31:16 2016 +0200
Branches: master
https://developer.blender.org/rB6311a9ff234aecb054121bf12ad03da6242fc092

Cycles: Support half and half4 textures.

This is an initial commit for half texture support in Cycles.
It adds the basic infrastructure inside of the ImageManager and support for these textures on CPU.

Supported:
* Half Float OpenEXR images (can be used for e.g HDRs or Normalmaps) now use 1/2 the memory, when loaded via disk (OIIO).

ToDo:
Various things like support for inbuilt half textures, GPU... will come later, step by step.

Part of my GSoC 2016.

===================================================================

M	intern/cycles/kernel/kernel_compat_cpu.h
M	intern/cycles/kernel/kernel_globals.h
M	intern/cycles/kernel/kernels/cpu/kernel.cpp
M	intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h
M	intern/cycles/render/image.cpp
M	intern/cycles/render/image.h
M	intern/cycles/render/scene.h
M	intern/cycles/util/util_half.h
M	intern/cycles/util/util_texture.h

===================================================================

diff --git a/intern/cycles/kernel/kernel_compat_cpu.h b/intern/cycles/kernel/kernel_compat_cpu.h
index bb303b3..c882b47 100644
--- a/intern/cycles/kernel/kernel_compat_cpu.h
+++ b/intern/cycles/kernel/kernel_compat_cpu.h
@@ -122,6 +122,17 @@ template<typename T> struct texture_image  {
 		return make_float4(r, r, r, 1.0f);
 	}
 
+	ccl_always_inline float4 read(half4 r)
+	{
+		return half4_to_float4(r);
+	}
+
+	ccl_always_inline float4 read(half r)
+	{
+		float f = half_to_float(r);
+		return make_float4(f, f, f, 1.0f);
+	}
+
 	ccl_always_inline int wrap_periodic(int x, int width)
 	{
 		x %= width;
@@ -486,8 +497,10 @@ typedef texture<uint4> texture_uint4;
 typedef texture<uchar4> texture_uchar4;
 typedef texture_image<float> texture_image_float;
 typedef texture_image<uchar> texture_image_uchar;
+typedef texture_image<half> texture_image_half;
 typedef texture_image<float4> texture_image_float4;
 typedef texture_image<uchar4> texture_image_uchar4;
+typedef texture_image<half4> texture_image_half4;
 
 /* Macros to handle different memory storage on different devices */
 
diff --git a/intern/cycles/kernel/kernel_globals.h b/intern/cycles/kernel/kernel_globals.h
index e06c68f..8e66a3a 100644
--- a/intern/cycles/kernel/kernel_globals.h
+++ b/intern/cycles/kernel/kernel_globals.h
@@ -37,8 +37,10 @@ struct VolumeStep;
 typedef struct KernelGlobals {
 	texture_image_uchar4 texture_byte4_images[TEX_NUM_BYTE4_CPU];
 	texture_image_float4 texture_float4_images[TEX_NUM_FLOAT4_CPU];
+	texture_image_half4 texture_half4_images[TEX_NUM_HALF4_CPU];
 	texture_image_float texture_float_images[TEX_NUM_FLOAT_CPU];
 	texture_image_uchar texture_byte_images[TEX_NUM_BYTE_CPU];
+	texture_image_half texture_half_images[TEX_NUM_HALF_CPU];
 
 #  define KERNEL_TEX(type, ttype, name) ttype name;
 #  define KERNEL_IMAGE_TEX(type, ttype, name)
diff --git a/intern/cycles/kernel/kernels/cpu/kernel.cpp b/intern/cycles/kernel/kernels/cpu/kernel.cpp
index d8a83f6..f11c85d 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel.cpp
+++ b/intern/cycles/kernel/kernels/cpu/kernel.cpp
@@ -154,6 +154,38 @@ void kernel_tex_copy(KernelGlobals *kg,
 			tex->extension = extension;
 		}
 	}
+	else if(strstr(name, "__tex_image_half4")) {
+		texture_image_half4 *tex = NULL;
+		int id = atoi(name + strlen("__tex_image_half4_"));
+		int array_index = id - TEX_START_HALF4_CPU;
+
+		if(array_index >= 0 && array_index < TEX_NUM_HALF4_CPU) {
+			tex = &kg->texture_half4_images[array_index];
+		}
+
+		if(tex) {
+			tex->data = (half4*)mem;
+			tex->dimensions_set(width, height, depth);
+			tex->interpolation = interpolation;
+			tex->extension = extension;
+		}
+	}
+	else if(strstr(name, "__tex_image_half")) {
+		texture_image_half *tex = NULL;
+		int id = atoi(name + strlen("__tex_image_half_"));
+		int array_index = id - TEX_START_HALF_CPU;
+
+		if(array_index >= 0 && array_index < TEX_NUM_HALF_CPU) {
+			tex = &kg->texture_half_images[array_index];
+		}
+
+		if(tex) {
+			tex->data = (half*)mem;
+			tex->dimensions_set(width, height, depth);
+			tex->interpolation = interpolation;
+			tex->extension = extension;
+		}
+	}
 	else
 		assert(0);
 }
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h b/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h
index b10861a..4738314 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h
+++ b/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h
@@ -23,7 +23,11 @@ CCL_NAMESPACE_BEGIN
 
 ccl_device float4 kernel_tex_image_interp_impl(KernelGlobals *kg, int tex, float x, float y)
 {
-	if(tex >= TEX_START_BYTE_CPU)
+	if(tex >= TEX_START_HALF_CPU)
+		return kg->texture_half_images[tex - TEX_START_HALF_CPU].interp(x, y);
+	else if(tex >= TEX_START_HALF4_CPU)
+		return kg->texture_half4_images[tex - TEX_START_HALF4_CPU].interp(x, y);
+	else if(tex >= TEX_START_BYTE_CPU)
 		return kg->texture_byte_images[tex - TEX_START_BYTE_CPU].interp(x, y);
 	else if(tex >= TEX_START_FLOAT_CPU)
 		return kg->texture_float_images[tex - TEX_START_FLOAT_CPU].interp(x, y);
@@ -35,7 +39,11 @@ ccl_device float4 kernel_tex_image_interp_impl(KernelGlobals *kg, int tex, float
 
 ccl_device float4 kernel_tex_image_interp_3d_impl(KernelGlobals *kg, int tex, float x, float y, float z)
 {
-	if(tex >= TEX_START_BYTE_CPU)
+	if(tex >= TEX_START_HALF_CPU)
+		return kg->texture_half_images[tex - TEX_START_HALF_CPU].interp_3d(x, y, z);
+	else if(tex >= TEX_START_HALF4_CPU)
+		return kg->texture_half4_images[tex - TEX_START_HALF4_CPU].interp_3d(x, y, z);
+	else if(tex >= TEX_START_BYTE_CPU)
 		return kg->texture_byte_images[tex - TEX_START_BYTE_CPU].interp_3d(x, y, z);
 	else if(tex >= TEX_START_FLOAT_CPU)
 		return kg->texture_float_images[tex - TEX_START_FLOAT_CPU].interp_3d(x, y, z);
@@ -48,7 +56,11 @@ ccl_device float4 kernel_tex_image_interp_3d_impl(KernelGlobals *kg, int tex, fl
 
 ccl_device float4 kernel_tex_image_interp_3d_ex_impl(KernelGlobals *kg, int tex, float x, float y, float z, int interpolation)
 {
-	if(tex >= TEX_START_BYTE_CPU)
+	if(tex >= TEX_START_HALF_CPU)
+		return kg->texture_half4_images[tex - TEX_START_HALF_CPU].interp_3d_ex(x, y, z, interpolation);
+	else if(tex >= TEX_START_HALF4_CPU)
+		return kg->texture_half_images[tex - TEX_START_HALF4_CPU].interp_3d_ex(x, y, z, interpolation);
+	else if(tex >= TEX_START_BYTE_CPU)
 		return kg->texture_byte_images[tex - TEX_START_BYTE_CPU].interp_3d_ex(x, y, z, interpolation);
 	else if(tex >= TEX_START_FLOAT_CPU)
 		return kg->texture_float_images[tex - TEX_START_FLOAT_CPU].interp_3d_ex(x, y, z, interpolation);
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index 71dc85f..c5e8195 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -54,10 +54,14 @@ ImageManager::ImageManager(const DeviceInfo& info)
 		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_num_images[IMAGE_DATA_TYPE_HALF4] = TEX_NUM_HALF4_ ## ARCH; \
+		tex_num_images[IMAGE_DATA_TYPE_HALF] = TEX_NUM_HALF_ ## 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; \
+		tex_start_images[IMAGE_DATA_TYPE_HALF4] = TEX_START_HALF4_ ## ARCH; \
+		tex_start_images[IMAGE_DATA_TYPE_HALF] = TEX_START_HALF_ ## ARCH; \
 	}
 
 	if(device_type == DEVICE_CPU) {
@@ -80,10 +84,14 @@ ImageManager::ImageManager(const DeviceInfo& info)
 		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_num_images[IMAGE_DATA_TYPE_HALF4] = 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_FLOAT] = 0;
 		tex_start_images[IMAGE_DATA_TYPE_BYTE] = 0;
+		tex_start_images[IMAGE_DATA_TYPE_HALF4] = 0;
+		tex_start_images[IMAGE_DATA_TYPE_HALF] = 0;
 		assert(0);
 	}
 
@@ -128,7 +136,7 @@ ImageManager::ImageDataType ImageManager::get_image_metadata(const string& filen
                                                              void *builtin_data,
                                                              bool& is_linear)
 {
-	bool is_float = false;
+	bool is_float = false, is_half = false;
 	is_linear = false;
 	int channels = 4;
 
@@ -167,6 +175,10 @@ ImageManager::ImageDataType ImageManager::get_image_metadata(const string& filen
 				}
 			}
 
+			/* check if it's half float */
+			if(spec.format == TypeDesc::HALF)
+				is_half = true;
+
 			channels = spec.nchannels;
 
 			/* basic color space detection, not great but better than nothing
@@ -192,7 +204,10 @@ ImageManager::ImageDataType ImageManager::get_image_metadata(const string& filen
 		delete in;
 	}
 
-	if(is_float) {
+	if(is_half) {
+		return IMAGE_DATA_TYPE_HALF4;
+	}
+	else if(is_float) {
 		return (channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_FLOAT;
 	}
 	else {
@@ -230,6 +245,10 @@ string ImageManager::name_from_type(int type)
 		return "float";
 	else if(type == IMAGE_DATA_TYPE_BYTE)
 		return "byte";
+	else if(type == IMAGE_DATA_TYPE_HALF4)
+		return "half4";
+	else if(type == IMAGE_DATA_TYPE_HALF)
+		return "half";
 	else
 		return "byte4";
 }
@@ -265,11 +284,16 @@ 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 CUDA (Fermi) and OpenCL, use available slots */
-	if(type == IMAGE_DATA_TYPE_FLOAT && tex_num_images[type] == 0)
+	/* No single channel and half textures on CUDA (Fermi) and OpenCL, use available slots */
+	if((type == IMAGE_DATA_TYPE_FLOAT ||
+	    type == IMAGE_DATA_TYPE_HALF4 ||
+	    type == IMAGE_DATA_TYPE_HALF) &&
+	    tex_num_images[type] == 0) {
 		type = IMAGE_DATA_TYPE_FLOAT4;
-	if(type == IMAGE_DATA_TYPE_BYTE && tex_num_images[type] == 0)
+	}
+	if(type == IMAGE_DATA_TYPE_BYTE && tex_num_images[type] == 0) {
 		type = IMAGE_DATA_TYPE_BYTE4;
+	}
 
 	/* Fnd existing image. */
 	for(slot = 0; slot < images[type].size(); slot++) {
@@ -645,6 +669,107 @@ bool ImageManager::file_load_float_image(Image *img, ImageDataType type, device_
 	return true;
 }
 
+template<typename T>
+bool ImageManager::file_load_half_image(Image *img, ImageDataType type, device_vector<T>& tex_img)
+{
+	ImageInput *in = NULL;
+	int width, height, depth, components;
+
+	if(!file_load_image_generic(img, &in, width, height, depth, components))
+		return false;
+
+	/* read RGBA pixels */
+	half *pixels = (half*)tex_img.resize(width, height, depth);
+	if(pixels == NULL) {
+		return false;
+	}
+
+	if(in) {
+		half *readpixels = pixels;
+		vector<half> tmppixels;
+
+		if(components > 4) {
+			tmppixels.resize(((size_t)width)*height*components);
+			readpixels = &tmppixels[0];
+		}
+
+		if(depth <= 1) {
+			int scanlinesize = width*components*sizeof(half);
+
+			in->read_image(TypeDesc::HALF,
+			               (uchar*)readpixels + (heig

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list