Budric
Budric

Reputation: 3699

OpenCL image2d and image3d memory layout

When transferring a 2d image stored in host memory to OpenCL, how is it reading the values - row major or column major? Let's assume row major.

index = row*NUM_COLS + col

How about 3d image stored in host memory? I believe that's treated as a stack of 2D images (which was assumed to be row major). Then pixel (row,col,slice) for limits (NUM_ROWS,NUM_COLS,NUM_SLICES) in terms of OpenCL is at:

index = slice*NUM_ROWS*NUM_COLS + row*NUM_COLS + col

However, according to wikipedia formulas the 3d Row Major indexing should be:

index = slice + NUM_SLICES*(col + NUM_COLS*row) 
      = row*NUM_COLS*NUM_SLICES + col*NUM_SLICES + slices

According to same article Column Major Ordering access should be:

index = row + NUM_ROWS*(col + NUM_COLS*slice)
      = slice*NUM_ROWS*NUM_COLS + col*NUM_ROWS + row

None of which seems to match what OpenCL is doing in 3d case.

So I guess I really have 2 questions

  1. How do I lay out my memory for transfering 2d and 3d images to OpenCL?
  2. Why does it seem like OpenCL has chosen a non standard memory layout in 3d case?

Edit

I view wikipedia article as a generic layout scheme. "row" or "column" are secondary label words. Whether you are dealing with tuples (row, col, slice) limited to (NUM_ROWS, NUM_COLS, NUM_SLICES) or (x,y,z) (WIDTH, HEIGHT, DEPTH) doesn't matter as long as it's consistent. It just tells you which dimension is continuous in memory. In "row major" it's the last dimension - z values that are next to each other, in column major it's the first dimension - x.

So once again I think "row major" layout for x,y,z 3d image indexing should have been:

index = z + DEPTH * (y + HEIGHT * x) = x * HEIGHT * DEPTH + y * HEIGHT + z

It isn't. But, I suppose you can chose whatever scheme you want.

Upvotes: 3

Views: 2053

Answers (1)

Christian Rau
Christian Rau

Reputation: 45948

First of all, your assumptions about the OpenCL layout are correct. OpenCL indeed uses the layout you describe and the formulas you provide for both the 2D and the 3D case are correct, component after component, pixel after pixel, row after row, slice after slice. And I (having an OpenGL background) consider this pretty standard.

Yet there is a bit of a naming confusion here, since what row-major in general means is what Wikipedia says, the first dimension changes with the lowest frequency and the last dimension is contiguous. Yet with images, the row isn't actually the first dimension, but the y-dimension, and columns are x. So while OpenCL (at least in 2D) uses literal "row-major" layout (since rows change less often), it is generally seen (in the terminology as used by Wikipedia) rather column-major, since the first dimension (x) is contiguous. And this translates well to 3D, where the last dimension (z) changes with lowest frequency. So you got Wikipedia wrong, what it is actually saying is that general column-major (as extended to 3D) is

index = z*WIDTH*HEIGHT + y*WIDTH + x

which, given that x=col and y=row, is indeed

index = slice*NUM_ROWS*NUM_COLS + row*NUM_COLS + col

which is exactly what OpenCL uses. So to answer you actual questions:

  1. Exactly like you explained in the first part of your question.

  2. Because you got Wikipedia wrong and confused matrix-based (row,col)-indexing with image-based (x,y)-indexing and what OpenCL uses corresponds to what Wikipedia generally calls column-major.

EDIT: This confusion of index-based addressing (like matrices) and coordinate-based addressing (like images) is a common source of confusion. For example in OpenCV (a famous image processing library) images are represented and addressed as matrices and thus like (row,col), which for an actual image means (y,x).

Upvotes: 3

Related Questions