Fix Cycles OpenCL not taking Extend and Clip extension types into account.
authorThomas Dinges <blender@dingto.org>
Fri, 1 Jul 2016 21:48:31 +0000 (23:48 +0200)
committerThomas Dinges <blender@dingto.org>
Fri, 1 Jul 2016 21:48:31 +0000 (23:48 +0200)
(See T48720).

intern/cycles/kernel/svm/svm_image.h
intern/cycles/render/image.cpp
intern/cycles/render/image.h

index aa9c07c867ec74b8b80cf94d35d697b07d195850..6a2248865d719665a3c4edb460ae1ca8184c54fb 100644 (file)
@@ -72,8 +72,16 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y,
        uint width = info.x;
        uint height = info.y;
        uint offset = info.z;
-       uint periodic = (info.w & 0x1);
-       uint interpolation = info.w >> 1;
+
+       /* Image Options */
+       uint interpolation = (info.w & (1 << 0)) ? INTERPOLATION_CLOSEST : INTERPOLATION_LINEAR;
+       uint extension;
+       if(info.w & (1 << 1))
+               extension = EXTENSION_REPEAT;
+       else if(info.w & (1 << 2))
+               extension = EXTENSION_EXTEND;
+       else
+               extension = EXTENSION_CLIP;
 
        float4 r;
        int ix, iy, nix, niy;
@@ -81,29 +89,37 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y,
                svm_image_texture_frac(x*width, &ix);
                svm_image_texture_frac(y*height, &iy);
 
-               if(periodic) {
+               if(extension == EXTENSION_REPEAT) {
                        ix = svm_image_texture_wrap_periodic(ix, width);
                        iy = svm_image_texture_wrap_periodic(iy, height);
                }
-               else {
+               else if(extension == EXTENSION_CLIP) {
+                       if(x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f)
+                               return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+               }
+               else { /* EXTENSION_EXTEND */
                        ix = svm_image_texture_wrap_clamp(ix, width);
                        iy = svm_image_texture_wrap_clamp(iy, height);
-
                }
+
                r = svm_image_texture_read(kg, id, offset + ix + iy*width);
        }
-       else { /* We default to linear interpolation if it is not closest */
+       else { /* INTERPOLATION_LINEAR */
                float tx = svm_image_texture_frac(x*width - 0.5f, &ix);
                float ty = svm_image_texture_frac(y*height - 0.5f, &iy);
 
-               if(periodic) {
+               if(extension == EXTENSION_REPEAT) {
                        ix = svm_image_texture_wrap_periodic(ix, width);
                        iy = svm_image_texture_wrap_periodic(iy, height);
 
                        nix = svm_image_texture_wrap_periodic(ix+1, width);
                        niy = svm_image_texture_wrap_periodic(iy+1, height);
                }
-               else {
+               else if(extension == EXTENSION_CLIP) {
+                       if(x < 0.0f || y < 0.0f || x > 1.0f || y > 1.0f)
+                               return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
+               }
+               else { /* EXTENSION_EXTEND */
                        ix = svm_image_texture_wrap_clamp(ix, width);
                        iy = svm_image_texture_wrap_clamp(iy, height);
 
@@ -111,7 +127,6 @@ ccl_device float4 svm_image_texture(KernelGlobals *kg, int id, float x, float y,
                        niy = svm_image_texture_wrap_clamp(iy+1, height);
                }
 
-
                r = (1.0f - ty)*(1.0f - tx)*svm_image_texture_read(kg, id, offset + ix + iy*width);
                r += (1.0f - ty)*tx*svm_image_texture_read(kg, id, offset + nix + iy*width);
                r += ty*(1.0f - tx)*svm_image_texture_read(kg, id, offset + ix + niy*width);
index ecde2e99a7be302e5ea484cb9cf031149f827031..d497661ee1de456342251ea16250a7fb7832885f 100644 (file)
@@ -1076,6 +1076,25 @@ void ImageManager::device_update_slot(Device *device,
        }
 }
 
+uint8_t ImageManager::pack_image_options(ImageDataType type, size_t slot)
+{
+       uint8_t options;
+       /* Image Options are packed into one uint:
+        * bit 0 -> Interpolation
+        * bit 1 + 2  + 3-> Extension */
+       if(images[type][slot]->interpolation == INTERPOLATION_CLOSEST)
+               options |= (1 << 0);
+
+       if(images[type][slot]->extension == EXTENSION_REPEAT)
+               options |= (1 << 1);
+       else if(images[type][slot]->extension == EXTENSION_EXTEND)
+               options |= (1 << 2);
+       else /* EXTENSION_CLIP */
+               options |= (1 << 3);
+
+       return options;
+}
+
 void ImageManager::device_pack_images(Device *device,
                                       DeviceScene *dscene,
                                       Progress& /*progess*/)
@@ -1107,11 +1126,9 @@ void ImageManager::device_pack_images(Device *device,
 
                device_vector<uchar4>& tex_img = dscene->tex_byte4_image[slot];
 
-               /* The image options are packed
-                  bit 0 -> periodic
-                  bit 1 + 2 -> interpolation type */
-               uint8_t interpolation = (images[type][slot]->interpolation << 1) + 1;
-               info[type_index_to_flattened_slot(slot, type)] = make_uint4(tex_img.data_width, tex_img.data_height, offset, interpolation);
+               uint8_t options = pack_image_options(type, slot);
+
+               info[type_index_to_flattened_slot(slot, type)] = make_uint4(tex_img.data_width, tex_img.data_height, offset, options);
 
                memcpy(pixels_byte+offset, (void*)tex_img.data_pointer, tex_img.memory_size());
                offset += tex_img.size();
@@ -1139,11 +1156,8 @@ void ImageManager::device_pack_images(Device *device,
 
                /* todo: support 3D textures, only CPU for now */
 
-               /* The image options are packed
-                  bit 0 -> periodic
-                  bit 1 + 2 -> interpolation type */
-               uint8_t interpolation = (images[type][slot]->interpolation << 1) + 1;
-               info[type_index_to_flattened_slot(slot, type)] = make_uint4(tex_img.data_width, tex_img.data_height, offset, interpolation);
+               uint8_t options = pack_image_options(type, slot);
+               info[type_index_to_flattened_slot(slot, type)] = make_uint4(tex_img.data_width, tex_img.data_height, offset, options);
 
                memcpy(pixels_float+offset, (void*)tex_img.data_pointer, tex_img.memory_size());
                offset += tex_img.size();
index 01d02f4dbec2783281950527313e5da13a6a405a..07998684b2346ca27bb04f594d84aa3f4629ec4e 100644 (file)
@@ -122,6 +122,8 @@ private:
        int flattened_slot_to_type_index(int flat_slot, ImageDataType *type);
        string name_from_type(int type);
 
+       uint8_t pack_image_options(ImageDataType type, size_t slot);
+
        void device_load_image(Device *device, DeviceScene *dscene, ImageDataType type, int slot, Progress *progess);
        void device_free_image(Device *device, DeviceScene *dscene, ImageDataType type, int slot);