简体   繁体   中英

Loading data into a 3D texture in Metal

From what I understood by reading the docs, a 3D texture only has 1 slice. When I try to load data into it though, it fails with error:

MTLTexture.m:504: failed assertion `imageBytes(0) must be >= (2048).'

The code used to load is (texture is type MTLPixelFormatRG16Uint and size elementsInRow * elementsInRow * elementsInRow ):

[texture replaceRegion:region mipmapLevel:0 withBytes:data bytesPerRow:sizeof(uint16_t) * 2 * elementsInRow];

where elementsInRow is 128 , region is MTLRegion region = MTLRegionMake3D(50, 50, 50, 4, 4, 4); and data is uint16_t data[region.size.depth][region.size.height][region.size.width][2] .

I also tried with:

[texture replaceRegion:region mipmapLevel:0 slice:0 data bytesPerRow:sizeof(uint16_t) * 2 * elementsInRow bytesPerImage:sizeof(uint16_t) * 2 * elementsInRow * elementsInRow];

but it results in a memory error.

See also here: https://forums.developer.apple.com/message/43332#43332

How can I correctly load data in a 3D region of a 3D texture?

UPDATE 1:

The second example works when the region has depth 1 and even bigger width and height (but with 32x32x1 it will crash).

UPDATE 2:

If I use 16x16x1 and write the same value for every pixel in the region, it seems to work, but when I export the data as an image, it looks like random data is being written instead, see this zoomed section of the image:

在此输入图像描述

If I run the test again, the image will have the same top section in uniform color, but the rest of the points will change intensity. Notice that I am writing the same value to every pixel, so the region should just be of uniform color.

That was it. I was trying to read from outside of boundaries memory, as the bytesPerRow and bytesPerImage parameters were not correct.

The documentation says:

bytesPerRow
For an ordinary or packed pixel format, the stride, in bytes, between rows of source data.

bytesPerImage
The stride, in bytes, between images in the source data.

I was passing the values thinking that they were referred to the texture , not the region .

So the code should be:

[texture replaceRegion:region mipmapLevel:0 slice:0 data bytesPerRow:sizeof(uint16_t) * 2 * region.size.width bytesPerImage:sizeof(uint16_t) * 2 * region.size.width * region.size.height];

You can never read the documentation carefully enough.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM