Introducción a Renderscript

En esta guía se presenta Renderscript y se explica cómo usar las API intrínsecas de Renderscript en una aplicación Xamarin.Android que tiene como destino el nivel de API 17 o posterior.

Información general

Renderscript es un marco de programación creado por Google con el fin de mejorar el rendimiento de las aplicaciones Android que requieren recursos de cálculo extensivos. Se trata de una API de bajo nivel y alto rendimiento basada en C99. Dado que se trata de una API de bajo nivel que se ejecutará en CPU, GPU o DSP, Renderscript es adecuado para aplicaciones Android que pueden necesitar realizar cualquiera de las siguientes acciones:

  • Gráficos
  • Procesamiento de imágenes
  • Cifrado
  • Procesamiento de señales
  • Rutinas matemáticas

Renderscript usará clang y compilará los scripts en el código de bytes de LLVM que se agrupa en APK. Cuando la aplicación se ejecuta por primera vez, el código de bytes de LLVM se compilará en el código máquina para los procesadores del dispositivo. Esta arquitectura permite a una aplicación Android aprovechar las ventajas del código máquina sin que los desarrolladores tengan que escribirlo para cada procesador en el propio dispositivo.

Hay dos componentes en una rutina de Renderscript:

  1. Tiempo de ejecución de Renderscript: se trata de las API nativas responsables de ejecutar Renderscript. Esto incluye cualquier script Renderscript escrito para la aplicación.

  2. Contenedores administrados de Android Framework: clases administradas que permiten que una aplicación Android controle e interactúe con el entorno de ejecución y los scripts de Renderscript. Además de las clases proporcionadas en el marco para controlar el tiempo de ejecución de Renderscript, la cadena de herramientas de Android examinará el código fuente de Renderscript y generará clases contenedoras administradas para que la aplicación Android las use.

El siguiente diagrama ilustra cómo se relacionan estos componentes:

Diagrama que ilustra cómo Interactúa Android Framework con renderscript Runtime

Hay tres conceptos importantes para el uso de Renderscripts en una aplicación Android:

  1. Un contexto: una API administrada proporcionada por el Android SDK que asigna recursos a Renderscript y permite que la aplicación Android pase y reciba datos de Renderscript.

  2. Un kernel de proceso: también conocido como kernel raíz o kernel,es una rutina que realiza el trabajo. El kernel es muy similar a una función de C; se trata de una rutina paralelizable que se ejecutará en todos los datos de la memoria asignada.

  3. Memoria asignada: los datos se pasan a y desde un kernel a través de una asignación. Un kernel puede tener una asignación de entrada o de salida.

El espacio de nombres Android.Renderscripts contiene las clases para interactuar con el tiempo de ejecución de Renderscript. En concreto, la clase Renderscript administrará el ciclo de vida y los recursos del motor de Renderscript. La aplicación Android debe inicializar uno o más objetos Android.Renderscripts.Allocation Objetos. Una asignación es una API administrada que es responsable de la asignación y el acceso a la memoria que se comparte entre la aplicación Android y el tiempo de ejecución de Renderscript. Normalmente, se crea una asignación para la entrada y, opcionalmente, se crea otra asignación que contiene la salida del kernel. El motor en tiempo de ejecución de Renderscript y las clases contenedoras administradas asociadas administrarán el acceso a la memoria mantenida por las asignaciones; no es necesario que un desarrollador de aplicaciones Android realice ningún trabajo adicional.

Una asignación contendrá uno o varios elementos Android.Renderscripts.Elements. Los elementos son un tipo especializado que describen los datos de cada asignación. Los tipos del elemento de la asignación de salida deben coincidir con los tipos del elemento de entrada. Al realizar la ejecución, un elemento Renderscript iterará en cada elemento de la asignación de entrada en paralelo y escribirá los resultados en la asignación de salida. Hay dos tipos de elementos:

  • tipo simple: conceptualmente, esto es lo mismo que un tipo de datos de C o char .

  • tipo complejo: este tipo es similar a C.

El motor de Renderscript realizará una comprobación en tiempo de ejecución para asegurarse de que los elementos de cada asignación son compatibles con lo que necesita el kernel. Si el tipo de datos de los elementos de la asignación no coincide con el tipo de datos que el kernel espera, se producirá una excepción.

Todos los kernels de Renderscript se encapsularán mediante un tipo que sea un descendiente de .ClaseAndroid.Renderscripts.Script . La clase Script se usa para establecer los parámetros de un elemento Renderscript, establecer el elemento Allocationsadecuado y ejecutar Renderscript. Hay dos subclases Script en Android SDK:

  • Android.Renderscripts.ScriptIntrinsic: algunas de las tareas de Renderscript más comunes se agrupan en el Android SDK y son accesibles mediante una subclase de la Android.Renderscripts.ScriptIntrinsic No es necesario que un desarrollador realice pasos adicionales para usar estos scripts en su aplicación, puesto que ya se proporcionan.

  • ScriptC_XXXXX – También conocido como ScriptC_XXXXXson scripts escritos por desarrolladores y empaquetados en el APK. En tiempo de compilación, la cadena de herramientas de Android generará clases contenedoras administradas que permitirán usar los scripts en la aplicación Android. El nombre de estas clases generadas es el nombre del archivo de Renderscript, con el prefijo ScriptC_. La escritura e incorporación de scripts de usuario no es compatible oficialmente con Xamarin.Android y va más allá del ámbito de esta guía.

De estos dos tipos, Xamarin.Android solo admite StringIntrinsic. En esta guía se explica cómo usar scripts intrínsecos en una aplicación Xamarin.Android.

Requisitos

Esta guía está destinada a las aplicaciones Xamarin.Android que tienen como destino el nivel de API 17 o posterior. El uso de scripts de usuario no se trata en esta guía.

La biblioteca de compatibilidad de Xamarin.Android V8 transporta las API de Renderscript intrínsecas para las aplicaciones destinadas a versiones anteriores de Android SDK. Agregar este paquete a un proyecto de Xamarin.Android debe permitir que las aplicaciones destinadas a versiones anteriores de Android SDK aprovechen los scripts intrínsecos.

Usar Renderscripts intrínsecos en Xamarin.Android

Los scripts intrínsecos son una excelente manera de realizar tareas informáticas intensivas con una cantidad mínima de código adicional. Se han optimizado para ofrecer un rendimiento óptimo en una gran sección de dispositivos cruzados. No es raro que un script intrínseco se ejecute 10 veces más rápido que el código administrado y 2 o 3 veces más tarde que una implementación personalizada de C. Muchos de los escenarios de procesamiento típicos están incluidos en los scripts intrínsecos. Esta lista de los scripts intrínsecos describe los scripts actuales de Xamarin.Android:

Consulte la documentación de la API para obtener más información sobre cada uno de los scripts intrínsecos.

A continuación, se describen los pasos básicos para usar Renderscript en una aplicación Android.

Crear un contexto de Renderscript: elRenderscript La clase es un contenedor administrado alrededor del contexto renderscript y controlará la inicialización, la administración de recursos y la limpieza. El objeto de Renderscript se crea mediante el método Factory Method RenderScript.Create, que adopta un contexto de Android (como una actividad) como parámetro. En la siguiente línea de código se muestra cómo inicializar el contexto de Renderscript:

Android.Renderscripts.RenderScript renderScript = RenderScript.Create(this);

Crear asignaciones: en función del script intrínseco, puede ser necesario crear uno o dos s. TheAndroid.Renderscripts.Allocation La clase tiene varios métodos de generador para ayudar a crear instancias de una asignación para un intrínseco. Como ejemplo, el fragmento de código siguiente muestra cómo crear una asignación para los mapas de bits.

Android.Graphics.Bitmap originalBitmap;
Android.Renderscripts.Allocation inputAllocation = Allocation.CreateFromBitmap(renderScript,
                                                     originalBitmap,
                                                     Allocation.MipmapControl.MipmapFull,
                                                     AllocationUsage.Script);

A menudo, será necesario crear un elemento Allocation para contener los datos de salida de un script. En el siguiente fragmento de código se muestra cómo usar la aplicación auxiliar de Allocation.CreateTyped para crear instancias de un segundo elemento Allocation que sea del mismo tipo que el original:

Android.Renderscripts.Allocation outputAllocation = Allocation.CreateTyped(renderScript, inputAllocation.Type);

Crear una instancia del contenedor de script: cada una de las clases contenedoras de script intrínsecas debe tener métodos auxiliares (normalmente denominados )para crear instancias de un objeto contenedor para ese script. El siguiente fragmento de código es un ejemplo de cómo crear una instancia de un objeto de desenfoque ScriptIntrinsicBlur. El método auxiliar Element.U8_4 creará un elemento que describe un tipo de datos que es 4 campos de valores enteros de 8 bits sin signo, adecuado para contener los datos de un objeto Bitmap:

Android.Renderscripts.ScriptIntrinsicBlur blurScript = ScriptIntrinsicBlur.Create(renderScript, Element.U8_4(renderScript));

Asignar asignaciones, establecer parámetros, Ejecutar script: la Script clase proporciona un método para ejecutar realmente ForEach Renderscript. Este método iterará en cada Element de Allocation que contiene los datos de entrada. En algunos casos, puede ser necesario proporcionar un elemento Allocation que contiene la salida. ForEach sobrescribirá el contenido de la asignación de salida. Para continuar con los fragmentos de código de los pasos anteriores, este ejemplo muestra cómo realizar una asignación de entrada, establecer un parámetro y, por último, ejecutar el script (copiando los resultados en la asignación de salida):

blurScript.SetInput(inputAllocation);
blurScript.SetRadius(25);  // Set a pamaeter
blurScript.ForEach(outputAllocation);

Puede consultar el artículo Desenfoque de una imagen con Renderscript, ya que se trata de un ejemplo completo de cómo usar un script intrínseco de Xamarin.Android.

Resumen

En esta guía se ha presentado Renderscript y cómo usarlo en una aplicación Xamarin.Android. Describe brevemente qué es Renderscript y cómo funciona en una aplicación Android. Describe algunos de los componentes clave de Renderscript y la diferencia entre scripts de usuario y scripts intrínsecos. Por último, en esta guía se describen los pasos para usar un script intrínseco en una aplicación Xamarin.Android.