【发布时间】:2019-06-03 14:16:38
【问题描述】:
我正在尝试使用MPSImageIntegral 来计算MTLTexture 中某些元素的总和。这就是我正在做的:
std::vector<float> integralSumData;
for(int i = 0; i < 10; i++)
integralSumData.push_back((float)i);
MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatR32Float
width:(integralSumData.size()) height:1 mipmapped:NO];
textureDescriptor.usage = MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite;
id<MTLTexture> texture = [_device newTextureWithDescriptor:textureDescriptor];
// Calculate the number of bytes per row in the image.
NSUInteger bytesPerRow = integralSumData.size() * sizeof(float);
MTLRegion region =
{
{ 0, 0, 0 }, // MTLOrigin
{integralSumData.size(), 1, 1} // MTLSize
};
// Copy the bytes from the data object into the texture
[texture replaceRegion:region
mipmapLevel:0
withBytes:integralSumData.data()
bytesPerRow:bytesPerRow];
MTLTextureDescriptor *textureDescriptor2 = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatR32Float
width:(integralSumData.size()) height:1 mipmapped:NO];
textureDescriptor2.usage = MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite;
id<MTLTexture> outtexture = [_device newTextureWithDescriptor:textureDescriptor2];
// Create a MPS filter.
MPSImageIntegral *integral = [[MPSImageIntegral alloc] initWithDevice: _device];
MPSOffset offset = { 0,0,0};
[integral setOffset:offset];
[integral setEdgeMode:MPSImageEdgeModeZero];
[integral encodeToCommandBuffer:commandBuffer sourceTexture:texture destinationTexture:outtexture];
[commandBuffer commit];
[commandBuffer waitUntilCompleted];
但是,当我检查我的 outtexture 值时,它全为零。难道我做错了什么?这是我使用MPSImageIntegral的正确方式吗?
我正在使用以下代码读取写入outTexture 的值:
float outData[100];
[outtexture getBytes:outData bytesPerRow:bytesPerRow fromRegion:region mipmapLevel:0];
for(int i = 0; i < 100; i++)
std::cout << outData[i] << "\n";
谢谢
【问题讨论】:
-
您是否提交了命令缓冲区(在您的代码中没有看到)?请注意,由于您使用的是 macOS,因此您还需要同步输出纹理,以便 CPU 可以读取它。
-
@MatthijsHollemans 是的,我确实提交了命令缓冲区。我忘了将它添加到我在 SO 上发布的示例代码中。我现在已将这些行添加到问题中。至于同步我加了
waitUntilCompleted,应该还不够吧? -
您还需要使用 MPSImage 的
synchronizeOnCommandBuffer。 -
@MatthijsHollemans 致电
synchronizeOnCommandBuffer谈什么?我不会在任何地方创建 MPSImage。可以在MPSImageIntegral上调用吗? -
哦,我的错,我在那里看到了 MPS,并假设您使用了 MPSImage 对象。如果您使用 MTLTextures,则需要使用
MTLBlitCommandEncoder进行同步。这会将纹理从 GPU 复制回 CPU。
标签: macos metal metal-performance-shaders