grid class replacement

Hello, my name is Tamer Afify, and I’m a test engineer on the C++ AMP team.  In this blog post, I will share a change in the C++ AMP API that you will observe with the VS 11 Beta (and beyond).

In the Visual Studio 11 Developer Preview, C++ AMP had a grid class that was basically an extent, plus an index object representing an origin. In the Beta we have removed grid from the programming model and instead you simply use an extent. Also the tiled_grid class was removed and a tiled_extent class is introduced with the same functionality that tiled_grid provided.

This means that any API that returned or accepted a grid or tiled_grid now returns or accepts an extent or tiled_extent. For all the user code we have seen, the (mostly) find and replace fix is fairly simple and mechanistic. The exception to the simple “find and replace” scenario is if you had actually set the origin parameter of grid to something other than the default zero index object.

An example where your data origin isn’t identical to your compute origin is the image blur problem which we will look at next.

For such a scenario you need to follow two systematic steps to convert your VS 11 Developer Preview code to the VS 11 Beta:

1. Wherever the grid type is used replace with extent

2. Instead of embedding the non-zero origin to the grid/extent, add the non-zero origin to the passed in index at the start of the kernel

Pixel blur is performed by changing every pixel RBG band value to the arithmetic average value for this pixel with all its 8 neighbor pixels. So to blur an image box of 8x8, you compute on the inner box 7x7 as the borders have no neighbors. So the compute origin is (1, 1), and the compute extent is smaller than the data extent by 2 rows and 2 columns.

This is a sample function (with VS 11 Developer Preview syntax) for using the grid class to do an image blur;

    1: array<float,2> boxblur(array_view<float,2> img)
    2: {
    3:   index<2> origin(1,1);
    4:   array<float, 2> blurimage(img);
    5:   grid<2> result(origin, img.grid.extent - extent<2>(2,2));
    6:  
    7:   parallel_for_each(result, [=, &blurimage](index<2> idx) 
    8:     restrict(direct3d)
    9:   {
   10:     float r = 0.0f;
   11:     int samples = 0;
   12:  
   13:  
   14:     for (int dy = -1; dy <= 1; dy++)
   15:     {
   16:       for (int dx = -1; dx <= 1; dx++)
   17:       {
   18:         r += img[idx + index<2>(dy,dx)];
   19:         samples++;
   20:       }
   21:     }
   22:  
   23:     blurimage[idx] = r/samples;
   24:   });
   25:  
   26:   return blurimage;
   27: }

By applying the steps we stated earlier the sample would be;

    1: array<float,2> boxblur(array_view<float,2> img)
    2: {
    3:   index<2> origin(1,1);
    4:   array<float, 2> blurimage(img);
    5:   extent<2> result(img.extent - extent<2>(2,2));
    6:  
    7:   parallel_for_each(result, [=, &blurimage](index<2> idx) 
    8:     restrict(amp)
    9:   {
   10:     float r = 0.0f;
   11:     int samples = 0;
   12:     idx += origin; 
   13:  
   14:     for (int dy = -1; dy <= 1; dy++)
   15:     {
   16:       for (int dx = -1; dx <= 1; dx++)
   17:       {
   18:         r += img[idx + index<2>(dy,dx)];
   19:         samples++;
   20:       }
   21:     }
   22:  
   23:     blurimage[idx] = r/samples;
   24:   });
   25:  
   26:   return blurimage;
   27: }

Notice we declared result as extent instead of grid (line 5) and used the new origin to adjust idx to match grid origin (line 12).

That concludes the example of replacing grid with extent, in the case where you used the origin of the grid using the VS 11 Developer Preview (for all other cases the find and replace mechanism should just work). You can download a ZIP file with two projects to try the above on your own machine. As usual, your feedback is welcome in our forum.

imgblur_grid.zip