首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在GPU渲染后访问MTLBuffer的内容?

如何在GPU渲染后访问MTLBuffer的内容?
EN

Stack Overflow用户
提问于 2021-08-30 15:45:39
回答 1查看 72关注 0票数 2

我正在开发一个OpenFX插件,用于在评分/后期制作软件中处理图像。

我的所有处理都是在一系列Metal内核函数中完成的。图像作为缓冲区(浮点数组)发送到GPU,一个用于输入,一个用于输出。

输出结果随后由OpenFX框架用于在宿主应用程序中显示,因此在此之前我不必处理它。

我现在需要在GPU处理完命令后能够读取输出值。我尝试使用应用于缓冲区的"contents“方法,但我的插件总是崩溃(在最坏的情况下),或者当它”工作“时给我非常奇怪的值(我不应该有任何大于1和小于0的值,但我得到了非常大的数字,0或负0,等等……所以我假设我有一个内存访问问题)。

起初,我认为这是私有/共享内存的问题,所以我尝试将缓冲区修改为共享。但我仍然在挣扎!

完全披露:我没有在MSL的具体培训,我正在学习,因为我去这个项目,所以我可能会做-或说非常愚蠢的事情。在决定寻求帮助之前,我已经环顾了几个小时。感谢所有愿意以任何方式帮助我们的人!

下面是代码(不包括与我当前问题无关的所有内容)。如果它缺少任何有趣的东西,请告诉我。

代码语言:javascript
复制
id < MTLBuffer > srcDeviceBuf = reinterpret_cast<id<MTLBuffer> >(const_cast<float*>(p_Input)) ;

//Below is the destination Image buffer creation the way it used to be done before my edits
//id < MTLBuffer > dstDeviceBuf = reinterpret_cast<id<MTLBuffer> >(p_Output);

//My attempt at creating a Shared memory buffer
MTLResourceOptions bufferOptions = MTLResourceStorageModeShared;
int bufferLength = sizeof(float)*1920*1080*4;
id <MTLBuffer> dstDeviceBuf = [device newBufferWithBytes:p_Output length:bufferLength options:bufferOptions];

id<MTLCommandBuffer> commandBuffer = [queue commandBuffer];
commandBuffer.label = [NSString stringWithFormat:@"RunMetalKernel"];

id<MTLComputeCommandEncoder> computeEncoder = [commandBuffer computeCommandEncoder];
//First method to be computed
[computeEncoder setComputePipelineState:_initModule];
int exeWidth = [_initModule threadExecutionWidth];

MTLSize threadGroupCount = MTLSizeMake(exeWidth, 1, 1);
MTLSize threadGroups = MTLSizeMake((p_Width + exeWidth - 1) / exeWidth,
        p_Height, 1);

[computeEncoder setBuffer:srcDeviceBuf offset: 0 atIndex: 0];
[computeEncoder setBuffer:dstDeviceBuf offset: 0 atIndex: 8];

//encodes first module to be executed
[computeEncoder dispatchThreadgroups:threadGroups threadsPerThreadgroup: threadGroupCount];

//Modules encoding
if (p_lutexport_on) {
    //Fills the image with patch values for the LUT computation
    [computeEncoder setComputePipelineState:_LUTExportModule];
    [computeEncoder dispatchThreadgroups:threadGroups threadsPerThreadgroup: threadGroupCount];
}

[computeEncoder endEncoding];
[commandBuffer commit];


if (p_lutexport_on) {
    
    //Here is where I try to read the buffer values (and inserts them into a custom object "p_lut_exp_lut"

    float* result = static_cast<float*>([dstDeviceBuf contents]);

    //Retrieve the output values and populate the LUT with them
    int lutLine = 0;
    float3 out;
    for (int index(0); index < 35937 * 4; index += 4) {
        out.x = result[index];
        out.y = result[index + 1];
        out.z = result[index + 2];

        p_lutexp_lut->setValuesAtLine(lutLine, out);
        lutLine++;
    }

    p_lutexp_lut->toFile();
}
EN

回答 1

Stack Overflow用户

发布于 2021-08-30 15:57:04

如果命令缓冲区包含对给定MTLBuffer的写入或读取操作,则必须确保在读取缓冲区内容之前完成这些操作。您可以使用addCompletedHandler:方法、waitUntilCompleted方法或自定义信号量来通知命令缓冲区已完成执行。

代码语言:javascript
复制
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> cb) {
    /* read or write buffer here */
}];
[commandBuffer commit];
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68986835

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档