[Bf-blender-cvs] [4d00e95ee3e] master: Cycles: Adding native support for UINT16 textures.

Stefan Werner noreply at git.blender.org
Thu Jul 5 13:53:36 CEST 2018


Commit: 4d00e95ee3ed91f86262bb218f1c5df901da724c
Author: Stefan Werner
Date:   Thu Jul 5 12:37:52 2018 +0200
Branches: master
https://developer.blender.org/rB4d00e95ee3ed91f86262bb218f1c5df901da724c

Cycles: Adding native support for UINT16 textures.

Textures in 16 bit integer format are sometimes used for displacement, bump and normal maps and can be exported by tools like Substance Painter. Without this patch, Cycles would promote those textures to single precision floating point, causing them to take up twice as much memory as needed.

Reviewers: #cycles, brecht, sergey

Reviewed By: #cycles, brecht, sergey

Subscribers: sergey, dingto, #cycles

Tags: #cycles

Differential Revision: https://developer.blender.org/D3523

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

M	intern/cycles/device/device_cuda.cpp
M	intern/cycles/device/device_memory.h
M	intern/cycles/kernel/CMakeLists.txt
M	intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h
M	intern/cycles/kernel/kernels/cuda/kernel_cuda_image.h
M	intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h
M	intern/cycles/render/image.cpp
M	intern/cycles/util/CMakeLists.txt
M	intern/cycles/util/util_half.h
M	intern/cycles/util/util_image_impl.h
M	intern/cycles/util/util_texture.h
M	intern/cycles/util/util_types.h
A	intern/cycles/util/util_types_ushort4.h

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

diff --git a/intern/cycles/device/device_cuda.cpp b/intern/cycles/device/device_cuda.cpp
index 8294af340e8..73c9697223d 100644
--- a/intern/cycles/device/device_cuda.cpp
+++ b/intern/cycles/device/device_cuda.cpp
@@ -1072,6 +1072,7 @@ public:
 		CUarray_format_enum format;
 		switch(mem.data_type) {
 			case TYPE_UCHAR: format = CU_AD_FORMAT_UNSIGNED_INT8; break;
+			case TYPE_UINT16: format = CU_AD_FORMAT_UNSIGNED_INT16; break;
 			case TYPE_UINT: format = CU_AD_FORMAT_UNSIGNED_INT32; break;
 			case TYPE_INT: format = CU_AD_FORMAT_SIGNED_INT32; break;
 			case TYPE_FLOAT: format = CU_AD_FORMAT_FLOAT; break;
diff --git a/intern/cycles/device/device_memory.h b/intern/cycles/device/device_memory.h
index 1138964f18c..b6f3c2913a5 100644
--- a/intern/cycles/device/device_memory.h
+++ b/intern/cycles/device/device_memory.h
@@ -43,6 +43,7 @@ enum MemoryType {
 enum DataType {
 	TYPE_UNKNOWN,
 	TYPE_UCHAR,
+	TYPE_UINT16,
 	TYPE_UINT,
 	TYPE_INT,
 	TYPE_FLOAT,
@@ -57,6 +58,7 @@ static inline size_t datatype_size(DataType datatype)
 		case TYPE_UCHAR: return sizeof(uchar);
 		case TYPE_FLOAT: return sizeof(float);
 		case TYPE_UINT: return sizeof(uint);
+		case TYPE_UINT16: return sizeof(uint16_t);
 		case TYPE_INT: return sizeof(int);
 		case TYPE_HALF: return sizeof(half);
 		case TYPE_UINT64: return sizeof(uint64_t);
@@ -156,6 +158,16 @@ template<> struct device_type_traits<half> {
 	static const int num_elements = 1;
 };
 
+template<> struct device_type_traits<ushort4> {
+	static const DataType data_type = TYPE_UINT16;
+	static const int num_elements = 4;
+};
+
+template<> struct device_type_traits<uint16_t> {
+	static const DataType data_type = TYPE_UINT16;
+	static const int num_elements = 1;
+};
+
 template<> struct device_type_traits<half4> {
 	static const DataType data_type = TYPE_HALF;
 	static const int num_elements = 4;
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index 95cdefdd94b..092bec08a51 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -287,6 +287,7 @@ set(SRC_UTIL_HEADERS
 	../util/util_types_uint3_impl.h
 	../util/util_types_uint4.h
 	../util/util_types_uint4_impl.h
+	../util/util_types_ushort4.h
 	../util/util_types_vector3.h
 	../util/util_types_vector3_impl.h
 )
diff --git a/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h b/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h
index 7bf833eadbc..b77b7350d86 100644
--- a/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h
+++ b/intern/cycles/kernel/kernels/cpu/kernel_cpu_image.h
@@ -35,13 +35,13 @@ template<typename T> struct TextureInterpolator  {
 
 	static ccl_always_inline float4 read(uchar4 r)
 	{
-		float f = 1.0f/255.0f;
+		float f = 1.0f / 255.0f;
 		return make_float4(r.x*f, r.y*f, r.z*f, r.w*f);
 	}
 
 	static ccl_always_inline float4 read(uchar r)
 	{
-		float f = r*(1.0f/255.0f);
+		float f = r * (1.0f / 255.0f);
 		return make_float4(f, f, f, 1.0f);
 	}
 
@@ -63,6 +63,18 @@ template<typename T> struct TextureInterpolator  {
 		return make_float4(f, f, f, 1.0f);
 	}
 
+	static ccl_always_inline float4 read(uint16_t r)
+	{
+		float f = r*(1.0f/65535.0f);
+		return make_float4(f, f, f, 1.0f);
+	}
+
+	static ccl_always_inline float4 read(ushort4 r)
+	{
+		float f = 1.0f/65535.0f;
+		return make_float4(r.x*f, r.y*f, r.z*f, r.w*f);
+	}
+
 	static ccl_always_inline float4 read(const T *data,
 	                                     int x, int y,
 	                                     int width, int height)
@@ -481,15 +493,21 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals *kg, int id, float x, fl
 			return TextureInterpolator<half>::interp(info, x, y);
 		case IMAGE_DATA_TYPE_BYTE:
 			return TextureInterpolator<uchar>::interp(info, x, y);
+		case IMAGE_DATA_TYPE_USHORT:
+			return TextureInterpolator<uint16_t>::interp(info, x, y);
 		case IMAGE_DATA_TYPE_FLOAT:
 			return TextureInterpolator<float>::interp(info, x, y);
 		case IMAGE_DATA_TYPE_HALF4:
 			return TextureInterpolator<half4>::interp(info, x, y);
 		case IMAGE_DATA_TYPE_BYTE4:
 			return TextureInterpolator<uchar4>::interp(info, x, y);
+		case IMAGE_DATA_TYPE_USHORT4:
+			return TextureInterpolator<ushort4>::interp(info, x, y);
 		case IMAGE_DATA_TYPE_FLOAT4:
-		default:
 			return TextureInterpolator<float4>::interp(info, x, y);
+		default:
+			assert(0);
+			return make_float4(TEX_IMAGE_MISSING_R, TEX_IMAGE_MISSING_G, TEX_IMAGE_MISSING_B, TEX_IMAGE_MISSING_A);
 	}
 }
 
@@ -502,15 +520,21 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals *kg, int id, float x,
 			return TextureInterpolator<half>::interp_3d(info, x, y, z, interp);
 		case IMAGE_DATA_TYPE_BYTE:
 			return TextureInterpolator<uchar>::interp_3d(info, x, y, z, interp);
+		case IMAGE_DATA_TYPE_USHORT:
+			return TextureInterpolator<uint16_t>::interp_3d(info, x, y, z, interp);
 		case IMAGE_DATA_TYPE_FLOAT:
 			return TextureInterpolator<float>::interp_3d(info, x, y, z, interp);
 		case IMAGE_DATA_TYPE_HALF4:
 			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_USHORT4:
+			return TextureInterpolator<ushort4>::interp_3d(info, x, y, z, interp);
 		case IMAGE_DATA_TYPE_FLOAT4:
-		default:
 			return TextureInterpolator<float4>::interp_3d(info, x, y, z, interp);
+		default:
+			assert(0);
+			return make_float4(TEX_IMAGE_MISSING_R, TEX_IMAGE_MISSING_G, TEX_IMAGE_MISSING_B, TEX_IMAGE_MISSING_A);
 	}
 }
 
diff --git a/intern/cycles/kernel/kernels/cuda/kernel_cuda_image.h b/intern/cycles/kernel/kernels/cuda/kernel_cuda_image.h
index 91ad289a858..a72fae5e1b1 100644
--- a/intern/cycles/kernel/kernels/cuda/kernel_cuda_image.h
+++ b/intern/cycles/kernel/kernels/cuda/kernel_cuda_image.h
@@ -127,11 +127,12 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals *kg, int id, float x, fl
 	const TextureInfo& info = kernel_tex_fetch(__texture_info, id);
 	CUtexObject tex = (CUtexObject)info.data;
 
-	/* float4, byte4 and half4 */
+	/* float4, byte4, ushort4 and half4 */
 	const int texture_type = kernel_tex_type(id);
 	if(texture_type == IMAGE_DATA_TYPE_FLOAT4 ||
 	   texture_type == IMAGE_DATA_TYPE_BYTE4 ||
-	   texture_type == IMAGE_DATA_TYPE_HALF4)
+	   texture_type == IMAGE_DATA_TYPE_HALF4 ||
+	   texture_type == IMAGE_DATA_TYPE_USHORT4)
 	{
 		if(info.interpolation == INTERPOLATION_CUBIC) {
 			return kernel_tex_image_interp_bicubic<float4>(info, tex, x, y);
@@ -164,7 +165,8 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals *kg, int id, float x,
 	const int texture_type = kernel_tex_type(id);
 	if(texture_type == IMAGE_DATA_TYPE_FLOAT4 ||
 	   texture_type == IMAGE_DATA_TYPE_BYTE4 ||
-	   texture_type == IMAGE_DATA_TYPE_HALF4)
+	   texture_type == IMAGE_DATA_TYPE_HALF4 ||
+	   texture_type == IMAGE_DATA_TYPE_USHORT4)
 	{
 		if(interpolation == INTERPOLATION_CUBIC) {
 			return kernel_tex_image_interp_bicubic_3d<float4>(info, tex, x, y, z);
diff --git a/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h b/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h
index faa9dd66d0e..011623130eb 100644
--- a/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h
+++ b/intern/cycles/kernel/kernels/opencl/kernel_opencl_image.h
@@ -54,11 +54,23 @@ ccl_device_inline float4 svm_image_texture_read(KernelGlobals *kg, const ccl_glo
 		float f = 1.0f/255.0f;
 		return make_float4(r.x*f, r.y*f, r.z*f, r.w*f);
 	}
+	/* Ushort4 */
+	else if(texture_type == IMAGE_DATA_TYPE_USHORT4) {
+		ushort4 r = tex_fetch(ushort4, info, offset);
+		float f = 1.0f/65535.f;
+		return make_float4(r.x*f, r.y*f, r.z*f, r.w*f);
+	}
 	/* Float */
 	else if(texture_type == IMAGE_DATA_TYPE_FLOAT) {
 		float f = tex_fetch(float, info, offset);
 		return make_float4(f, f, f, 1.0f);
 	}
+	/* UShort */
+	else if(texture_type == IMAGE_DATA_TYPE_USHORT) {
+		ushort r = tex_fetch(ushort, info, offset);
+		float f = r * (1.0f / 65535.0f);
+		return make_float4(f, f, f, 1.0f);
+	}
 	/* Byte */
 	else {
 		uchar r = tex_fetch(uchar, info, offset);
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index 9c6536edc4f..3c49d17aa82 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -39,6 +39,10 @@ static bool isfinite(half /*value*/)
 {
 	return false;
 }
+static bool isfinite(uint16_t  /*value*/)
+{
+	return false;
+}
 
 ImageManager::ImageManager(const DeviceInfo& info)
 {
@@ -164,23 +168,27 @@ bool ImageManager::get_image_metadata(const string& filename,
 	metadata.height = spec.height;
 	metadata.depth = spec.depth;
 
-	/* check the main format, and channel formats;
-	 * if any take up more than one byte, we'll need a float texture slot */
-	if(spec.format.basesize() > 1) {
+
+	/* Check the main format, and channel formats. */
+	size_t channel_size = spec.format.basesize();
+
+	if(spec.format.is_floating_point()) {
 		metadata.is_float = true;
 		metadata.is_linear = true;
 	}
 
 	for(size_t channel = 0; channel < spec.channelformats.size(); channel++) {
-		if(spec.channelformats[channel].basesize() > 1) {
+		channel_size = max(channel_size, spec.channelformats[channel].basesize());
+		if(spec.channelformats[channel].is_floating_point()) {
 			metadata.is_float = true;
 			metadata.is_linear = true;
 		}
 	}
 
 	/* check if it's half float */
-	if(spec.format == TypeDesc::HALF)
+	if(spec.format == TypeDesc::HALF) {
 		metadata.is_half = true;
+	}
 
 	/* basic color space detection, not great but better than nothing
 	 * before we do OpenColorIO integration */
@@ -208,6 +216,9 @@ bool ImageManager::get_image_metadata(const string& filename,
 	else if(metadata.is_float) {
 		metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_FLOAT;
 	}
+	else if(spec.format == TypeDesc::USHORT) {
+		metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_USHORT4 : IMAGE_DATA_TYPE_USHORT;
+	}
 	else {
 		metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_BYTE4 : IMAGE_DATA_TYPE_BYTE;
 	}
@@ -254,6 +265,10 @@ string ImageManager::name_from_type(int type)
 		return "half4";
 	else if(type == IMAGE_DATA_TYPE_HALF)
 		return "half";
+	else if(type == IMAGE

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list