Search Unity

  1. All Pro and Enterprise subscribers: find helpful & inspiring creative, tech, and business know-how in the new Unity Success Hub. Sign in to stay up to date.
    Dismiss Notice
  2. Dismiss Notice

Help Wanted Simple Tensor Math in Barracuda

Discussion in 'Barracuda' started by hellovivian, Jun 8, 2020.

  1. hellovivian


    Jan 7, 2018
    In my last post I mentioned that when I use a texture as a tensor input ( as in Tensor(RenderTexture), I need to normalize the texture values between [-1,1] instead of [0,1]

    I iterated through my inputTensor and changed every index like so, effectively sending the texture back to the CPU:

    Code (CSharp):
    1. for (int y = 0; y < 256; y++) {
    2.             for (int x = 0; x < 256; x++) {              
    3.                 float r = (outputTensor[0,y,x,0] + 1.0f) / 2.0f;
    4.                 float g = (outputTensor[0,y,x,1] + 1.0f) / 2.0f;
    5.                 float b = (outputTensor[0,y,x,2] + 1.0f) / 2.0f;
    6.                 outputTensor[0,y,x,0] =  r;
    7.                 outputTensor[0,y,x,1] =  g;
    8.                 outputTensor[0,y,x,2] =  b;
    10.             }
    11.         }
    To make my application faster, I am trying to use a CustomRenderTexture with a fragment shader to normalize the values, but this seemed to not have the same effect.

    I am wondering two things:
    1. What is the simplest efficient way to implement normalization with Barracuda? Can I do tensor math with the Tensor class?
    2. Additionally, are CustomRenderTextures supported in the same way as normal render textures. If I call Tensor(CustomRenderTexture) on the CustomRenderTexture, will the values be the ones the shader has already changed?

    Here is an example of how my shader has been edited for normalization:
    Code (CSharp):
    1. float4 frag(v2f_customrendertexture IN) : COLOR
    2.             {
    3.                 return (0.5 * (_Color * (tex2D(_Tex, IN.localTexcoord.xy)) + 1));
    4.             }
    Thank you for reading!
  2. hellovivian


    Jan 7, 2018
    Okay, I shall answer my own question again. ;)

    1. Yes we can do tensor math, I was looking at the older documentation for Barracuda, but 1.0 Barracuda discusses how you can initialize arrays.
    2. Yes, at least for my project that is the case

    I do have another question though, which is: how do we slice into our output tensors? For example if we ran a batch input tensor and get back an output tensor in the shape of (2, 256, 256, 3)--how do we separate that output tensor into (1, 256, 256, 3) and (1,256,256,3) --without explicitly reading back the srcData /source data of the tensor?
    amirebrahimi_unity likes this.
  3. ReJ


    Unity Technologies

    Nov 1, 2008
    Sorry for late reply, just found your post.

    There are two ways to do it:
    1) Use ModelBuilder and add StridedSlice node at the end of your model.

    Code (CSharp):
    1. var builder = new ModelBuilder(model);
    2. var slice1 = builder.StridedSlice("slice1", model.outputs[0], starts:new[] { 0, 0,0,0}, ends:[] {1,256,256,3}, strides:new[]{1,1,1,1} };
    3. var slice2 = builder.StridedSlice("slice2", model.outputs[0], starts:new[] { 1, 0,0,0}, ends:[] {2,256,256,3}, strides:new[]{1,1,1,1} };
    4. builder.Output(slice1); // optional, if you want to use it as the final output
    5. builder.Output(slice2); // optional, if you want to use it as the final output
    6. model = builder.model; // take the updated model from the builder
    2) If you want to get the results into the RenderTexture and you have batch > 1 in the Tensor:

    Code (CSharp):
    1. var output = worker.Execute().PeekOutput();
    2. RenderTexture texSlice1 = output.ToRenderTexture(batch:0);
    3. RenderTexture texSlice2 = output.ToRenderTexture(batch:1);
    Hope it helps.