将数据加载到 Metal 中的 3D 纹理中
Loading data into a 3D texture in Metal
根据我阅读文档的理解,3D 纹理只有 1 个切片。但是,当我尝试将数据加载到其中时,它失败并显示错误:
MTLTexture.m:504: failed assertion `imageBytes(0) must be >= (2048).'
用于加载的代码是(纹理类型MTLPixelFormatRG16Uint
大小elementsInRow * elementsInRow * elementsInRow
):
[texture replaceRegion:region mipmapLevel:0 withBytes:data bytesPerRow:sizeof(uint16_t) * 2 * elementsInRow];
其中 elementsInRow
为 128
,区域为 MTLRegion region = MTLRegionMake3D(50, 50, 50, 4, 4, 4);
,数据为 uint16_t data[region.size.depth][region.size.height][region.size.width][2]
。
我也试过:
[texture replaceRegion:region mipmapLevel:0 slice:0 data bytesPerRow:sizeof(uint16_t) * 2 * elementsInRow bytesPerImage:sizeof(uint16_t) * 2 * elementsInRow * elementsInRow];
但它会导致内存错误。
另见此处:https://forums.developer.apple.com/message/43332#43332
如何在 3D 纹理的 3D 区域中正确加载数据?
更新 1:
当区域的深度为 1
甚至更大 width
和 height
时,第二个示例有效(但是 32x32x1
它会崩溃)。
更新 2:
如果我使用 16x16x1
并为该区域中的每个像素写入相同的值,这似乎可行,但是当我将数据导出为图像时,看起来像是写入了随机数据,查看图像的这个放大部分:
如果我 运行 再次测试,图像将具有相同的顶部颜色均匀的部分,但其余点将改变强度。请注意,我正在为每个像素写入相同的值,因此该区域应该具有统一的颜色。
就是这样。我试图从边界内存之外读取,因为 bytesPerRow
和 bytesPerImage
参数不正确。
文档说:
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.
我传递的值认为它们指的是纹理,而不是区域。
所以代码应该是:
[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];
您永远不会足够仔细地阅读文档。
根据我阅读文档的理解,3D 纹理只有 1 个切片。但是,当我尝试将数据加载到其中时,它失败并显示错误:
MTLTexture.m:504: failed assertion `imageBytes(0) must be >= (2048).'
用于加载的代码是(纹理类型MTLPixelFormatRG16Uint
大小elementsInRow * elementsInRow * elementsInRow
):
[texture replaceRegion:region mipmapLevel:0 withBytes:data bytesPerRow:sizeof(uint16_t) * 2 * elementsInRow];
其中 elementsInRow
为 128
,区域为 MTLRegion region = MTLRegionMake3D(50, 50, 50, 4, 4, 4);
,数据为 uint16_t data[region.size.depth][region.size.height][region.size.width][2]
。
我也试过:
[texture replaceRegion:region mipmapLevel:0 slice:0 data bytesPerRow:sizeof(uint16_t) * 2 * elementsInRow bytesPerImage:sizeof(uint16_t) * 2 * elementsInRow * elementsInRow];
但它会导致内存错误。
另见此处:https://forums.developer.apple.com/message/43332#43332
如何在 3D 纹理的 3D 区域中正确加载数据?
更新 1:
当区域的深度为 1
甚至更大 width
和 height
时,第二个示例有效(但是 32x32x1
它会崩溃)。
更新 2:
如果我使用 16x16x1
并为该区域中的每个像素写入相同的值,这似乎可行,但是当我将数据导出为图像时,看起来像是写入了随机数据,查看图像的这个放大部分:
如果我 运行 再次测试,图像将具有相同的顶部颜色均匀的部分,但其余点将改变强度。请注意,我正在为每个像素写入相同的值,因此该区域应该具有统一的颜色。
就是这样。我试图从边界内存之外读取,因为 bytesPerRow
和 bytesPerImage
参数不正确。
文档说:
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.
我传递的值认为它们指的是纹理,而不是区域。
所以代码应该是:
[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];
您永远不会足够仔细地阅读文档。