在 Renderscript Compute 中将数组传递给 rsForEach [英] Passing Array to rsForEach in Renderscript Compute

查看:19
本文介绍了在 Renderscript Compute 中将数组传递给 rsForEach的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我发现 RenderScript 中缺乏好的文档,据我所知,RS 中的 forEach 是为分配中的每个单独项目执行 root().

I found there's lacking good documentation in RenderScript, for what I know, forEach in RS is to execute the root() for each individual item in the allocation.

我正在尝试为进行图像处理的 Renderscript 制作一个库,作为起点,我达到了这个

I am trying to make a library for Renderscript that does Image processing, as a starting point, I reached this great answer. But the problem, is that the blur operation is on Each pixel and each pixel requires another loop (n with blur width) of calculation. Although running on multi-core, it is still a bit too slow.

我正在尝试修改它以允许(两次通过)框过滤器,但这需要处理单行或单列而不是单元格.那么,有什么办法可以让foreach给root()发送一个数组吗?

I am trying to modify it to allow (two-pass) box filter, but that requires working on a single row or column instead of cell. So, is there any way to ask foreach to send an array to root()?

推荐答案

rsForEach 只能对 Allocations 进行操作.

rsForEach can only operate upon Allocations.

如果您想让 rsForEach 函数为每个图像行调用 root(),您必须传入一个大小与行数相同的分配,然后计算出您应该是哪一行在 root() 内部操作(类似于对每一列进行操作).然后,RenderScript 应该划分工作以在可用资源上运行(在多核设备上同时处理多于一行).

If you want to have the rsForEach function call root() for each of the image rows you have to pass in an Allocation that is sized to be the same length as the number of rows and then work out which row you should be operating on inside root() (similarly for operating on each column). RenderScript should then divide up the work to run on the resources available (more than one row being processed at the same time on multi core devices).

您可以这样做的一种方法是传入一个分配,该分配给出图像行的偏移量(在图像数据数组内).root() 中的 v_in 参数将是行偏移量.由于 rsForEach 调用操作的分配不是图像数据,因此您不能使用 v_out 参数写出图像,必须单独绑定输出图像.

One way you could do that is by passing in an Allocation that give the offsets (within the image data array) of the image rows. The v_in argument inside the root() will then be the row offset. Since the Allocations the rsForEach call is operating upon is not the image data you cannot write the image out using the v_out argument and you must bind the output image separately.

以下是一些显示此内容的 RenderScript:

Here is some RenderScript that show this:

#pragma version(1)
#pragma rs java_package_name(com.android.example.hellocompute)

rs_allocation gIn;
rs_allocation gOut;
rs_script gScript;

int mImageWidth;
const uchar4 *gInPixels;
uchar4 *gOutPixels;

void init() {
}

static const int kBlurWidth = 20;

//
// This is called per row.
// The row indices are passed in as v_in or you could also use the x argument and multiply it by image width.
//
void root(const int32_t *v_in, int32_t *v_out, const void *usrData, uint32_t x, uint32_t y) {
    float3 blur[kBlurWidth];
    float3 cur_colour = {0.0f, 0.0f, 0.0f};

    for ( int i = 0; i < kBlurWidth; i++) {
        float3 init_colour = {0.0f, 0.0f, 0.0f};
        blur[i] = init_colour;
    }

    int32_t row_index = *v_in;
    int blur_index = 0;

    for ( int i = 0; i < mImageWidth; i++) {
        float4 pixel_colour = rsUnpackColor8888(gInPixels[i + row_index]);

        cur_colour -= blur[blur_index];
        blur[blur_index] = pixel_colour.rgb;
        cur_colour += blur[blur_index];

        blur_index += 1;
        if ( blur_index >= kBlurWidth) {
            blur_index = 0;
        }

        gOutPixels[i + row_index] = rsPackColorTo8888(cur_colour/(float)kBlurWidth);
        //gOutPixels[i + row_index] = rsPackColorTo8888(pixel_colour);
    }
}


void filter() {
    rsDebug("Number of rows:", rsAllocationGetDimX(gIn));
    rsForEach(gScript, gIn, gOut, NULL);
}

这将使用以下 Java 进行设置:

This would be setup using the following Java:

    mBlurRowScript = new ScriptC_blur_row(mRS, getResources(), R.raw.blur_row);

    int row_width = mBitmapIn.getWidth();

    //
    // Create an allocation that indexes each row.
    //
    int num_rows = mBitmapIn.getHeight();
    int[] row_indices = new int[num_rows];
    for ( int i = 0; i < num_rows; i++) {
        row_indices[i] = i * row_width;
    }
    Allocation row_indices_alloc = Allocation.createSized( mRS, Element.I32(mRS), num_rows, Allocation.USAGE_SCRIPT);
    row_indices_alloc.copyFrom(row_indices);

    //
    // The image data has to be bound to the pointers within the RenderScript so it can be accessed
    // from the root() function.
    //
    mBlurRowScript.bind_gInPixels(mInAllocation);
    mBlurRowScript.bind_gOutPixels(mOutAllocation);

    // Pass in the image width
    mBlurRowScript.set_mImageWidth(row_width);

    //
    // Pass in the row indices Allocation as the input. It is also passed in as the output though the output is not used.
    //
    mBlurRowScript.set_gIn(row_indices_alloc);
    mBlurRowScript.set_gOut(row_indices_alloc);
    mBlurRowScript.set_gScript(mBlurRowScript);
    mBlurRowScript.invoke_filter();

这篇关于在 Renderscript Compute 中将数组传递给 rsForEach的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆