Renderscript, forEach_root и портирование из OpenCL

1) Как я могу получить доступ к другим элементам forEach_root(), кроме текущего?

В OpenCL у нас есть указатель на первый элемент, а затем мы можем использовать get_global_id(0) для получения текущего индекса. Но мы по-прежнему можем получить доступ ко всем остальным элементам. В Renderscript у нас есть только указатель на текущий элемент?

2) Как я могу перебрать выделение в forEach_root()?

У меня есть код, который использует вложенный (двойной) цикл в java. Renderscript автоматизирует внешний цикл, но я не могу найти никакой информации о реализации внутреннего цикла. Ниже приведены мои лучшие усилия:

void root(const float3 *v_in, float3 *v_out) {
  rs_allocation alloc = rsGetAllocation(v_in);
  uint32_t cnt = rsAllocationGetDimX(alloc);
  *v_out = 0;
  for(int i=0; i<cnt; i++)  
    *v_out += v_in[i];
}

Но здесь rsGetAllocation() не работает при вызове из forEach_root().

05-11 21:31:29.639: E/RenderScript(17032): ScriptC::ptrToAllocation, failed to find 0x5beb1a40

На всякий случай добавлю свой код OpenCL, который отлично работает под Windows. Я пытаюсь портировать его на Renderscript

typedef float4 wType;

__kernel void gravity_kernel(__global wType *src,__global wType *dst)
{
  int id = get_global_id(0);
  int count = get_global_size(0);
  double4 tmp = 0;
  for(int i=0;i<count;i++) {
    float4 diff = src[i] - src[id];
    float sq_dist = dot(diff, diff);
    float4 norm = normalize(diff);
    if (sq_dist<0.5/60)
      tmp += convert_double4(norm*sq_dist);
    else
      tmp += convert_double4(norm/sq_dist);
  }
  dst[id] = convert_float4(tmp);
}

person Anton Duzenko    schedule 11.05.2013    source источник


Ответы (1)


Вы можете предоставить данные помимо вашей корневой функции. В текущей версии Android (4.2) вы можете сделать следующее (это пример из сценария обработки изображений):

Фрагмент рендерскрипта:

#pragma version(1)
#pragma rs java_package_name(com.example.renderscripttests)

//Define global variables in your renderscript:
rs_allocation pixels;
int width;
int height;

// And access these in your root function via rsGetElementAt(pixels, px, py)
void root(uchar4 *v_out, uint32_t x, uint32_t y)
{
    for(int px = 0; px < width; ++px)
        for(int py = 0; py < height; ++py)
        {
            // unpack a color to a float4
            float4 f4 = rsUnpackColor8888(*(uchar*)rsGetElementAt(pixels, px, py));
            ...

Фрагмент файла Java

// In your java file, create a renderscript:
RenderScript renderscript = RenderScript.create(this);

ScriptC_myscript script = new ScriptC_myscript(renderscript);

// Create Allocations for in- and output (As input the bitmap 'bitmapIn' should be used):
Allocation pixelsIn = Allocation.createFromBitmap(renderscript, bitmapIn,
         Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
Allocation pixelsOut = Allocation.createTyped(renderscript, pixelsIn.getType());

// Set width, height and pixels in the script:
script.set_width(640);
script.set_height(480);
script.set_pixels(pixelsIn);

// Call the for each loop:
script.forEach_root(pixelsOut);

// Copy Allocation to the bitmap 'bitmapOut':
pixelsOut.copyTo(bitmapOut);

Вы можете видеть, что ввод 'pixelsIn' ранее установлен и используется внутри скрипта рендеринга при вызове функции forEach_root для вычисления значений для 'pixelsOut'. Также предварительно задаются ширина и высота.

person stefank    schedule 11.05.2013
comment
Спасибо! Но если в вашем примере есть 2 потока, будут ли они выполнять одну и ту же работу? Оба потока будут проходить через одни и те же пиксели? Другой вопрос: x и y объявлены дважды в вашем примере? - person Anton Duzenko; 12.05.2013
comment
Я еще не пробовал, столкнутся ли два потока на стороне Java с использованием одного и того же скрипта. В случае, если «новый ScriptC_myscript (renderscript);» создавать разные объекты на стороне рендерскрипта, я предполагаю, что это должно работать. Я отредактировал x и y в двух циклах на px и py. (X и y относятся к «позиции» «v_out» - person stefank; 12.05.2013
comment
Я вижу, вы имели в виду темы «за кулисами». Renderscript root() вызывается для каждого элемента внутри 'pixelsOut' на стороне java - эта работа может выполняться несколькими потоками одновременно. Такой элемент представлен 'v_out' на стороне скрипта рендеринга. В этом примере вы можете вычислить каждый элемент 'v_out' в позициях 'x' и 'y', что предоставляется автоматически, но получить доступ ко всем 'пикселям' rs_allocation, как показано в двух циклах for. - person stefank; 12.05.2013
comment
Исчерпывающее объяснение! - person Anton Duzenko; 12.05.2013