Skip navigation

Második példa

Bevezetés

Ebben a példában az OpenCL képobjektumot fogjuk használni az előző feladatban megfogalmazott problémára.

Gazdagép kód

Először áttekintjük azokat a módosításokat, amelyek a gazdagép kódjában kell végrehajtanunk a képobjektum használatához.

Mindenképpen érdemes leellenőrizni, hogy az adott eszköz támogatja-e a képobjektum kezelését.

cl_bool imageSupport = CL_FALSE;
	
clGetDeviceInfo(device, CL_DEVICE_IMAGE_SUPPORT, sizeof(cl_bool), &imageSupport, NULL);

if (imageSupport != CL_TRUE)
{
  std::cerr << "OpenCL device does not support images." << std::endl;

  Cleanup(context, commandQueue, program, kernel, imgObjects);

  return 1;
}

Ha az eszköz támogatja a képobjektumok kezelését, akkor szükségünk van memória objektumra, amit a main programban definiálunk.

cl_mem imgObjects[1] = { 0 };

Ezután be kell állítranunk a képformátumra jellemző tulajdonságokat

cl_image_format clImageFormat; 
clImageFormat.image_channel_order = CL_BGRA;
clImageFormat.image_channel_data_type = CL_UNORM_INT8;

Majd ezután létrehozzuk a 2Ds textúraképet tartalmazó memória területet.

imgObjects[0] = clCreateImage2D(context, CL_MEM_WRITE_ONLY, &clImageFormat, N, N, 0, NULL,&errNum);

A kernel paraméterek beállítása és a kernel elhelyezése a parancssorban hasonlóan kell elvégezni, mint az előző példában. A kernel lefutása után a képobjektumból a gazdagép memóriájába kell másolni az eredményt.

unsigned char* result = new  unsigned char[N * N * 4];
size_t origin[3] = { 0, 0, 0 };
size_t region[3] = { N, N, 1 };
errNum = clEnqueueReadImage(commandQueue, imgObjects[0], CL_TRUE, origin, region, 0, 0, result, 0, NULL, NULL);

Végezetül pedig kiírjuk az eredményt egy png tipusú állományba.

SaveImage("image.bmp", result, N, N);

A teljes program innen tölthető le.

Eszköz kód

Az eszköz kódban a kimeneti 2D-s képobjektumot kell feltölteni  a write_imagef függvény segítségével.

// Add you device OpenCL code
__kernel void helloWave(__write_only image2d_t output, int width)
{
    int x = get_global_id(0);
    int y = get_global_id(1);

    float halfWidth = width/2.0f;
    float dist = sqrt((float)((x-halfWidth)*(x-halfWidth)+(y-halfWidth)*(y-halfWidth)));
    float value = cos(dist) + 1;;

    if (x < width && y < width)
    { 	
      write_imagef(output, (int2)(x, y) , (float4)(value, value, value,0));
    }
}

A forrás letölthető itt.

Feladat

  • Fordítsuk le a példát!
  • Változtassuk meg az eszköz kódot, hogy más mintázatot kapjunk!