В настоящее время у меня есть один пиксельный буфер, и я обрабатываю данные в нем одним вызовом ядра:
dim3 threadsPerBlock(32, 32)
dim3 blocks(screenWidth / threadsPerBlock.x, screenHeight / threadsPerBlock.y);
kernel<<<blocks, threadsPerBlock>>>();
Буфер пикселей содержит все пиксели окна с размерами screenWidth x screenHeight.
Моя идея состоит в том, чтобы разделить окно на 2 или 4 части и одновременно обрабатывать данные о пикселях.
Можно ли это сделать, и если можно, то как?
Я мало читал о потоках, но из того, что я понял, два потока не могут работать с одним фрагментом данных (например, с моим пиксельным буфером), или я ошибаюсь?
Редактировать: Моя видеокарта с вычислительными возможностями 3.0
Изменить 2: я использую SDL для рисования, у меня есть один графический процессор, и я использую пользовательский массив данных:
main.ru
Color vfb_linear[VFB_MAX_SIZE * VFB_MAX_SIZE]; // array on the Host
Color vfb[VFB_MAX_SIZE][VFB_MAX_SIZE] // 2D array used for SDL
extern "C" void callKernels(Color* dev_vfb);
int main()
{
Color* dev_vfb; // pixel array used on the GPU
// allocate memory for dev_vfb on the GPU
cudaMalloc((void**)&dev_vfb, sizeof(Color) * RES_X * RES_Y);
// memcpy HostToDevice
cudaMemcpy(dev_vfb, vfb_linear, sizeof(Color) * RES_X * RES_Y, cudaMemcpyHostToDevice);
callKernels(dev_vfb); // wrapper function that calls the kernels
// memcpy DeviceToHost
cudaMemcpy(vfb_linear, dev_vfb, sizeof(Color) * RES_X * RES_Y, cudaMemcpyDeviceToHost);
// convert vfb_linear into 2D array so it can be handled by SDL
convertDeviceToHostBuffer();
display(vfb); // render pixels on screen with SDL
}
cudaRenderer.cu
__global__ void kernel(Color* dev_vfb)
{
int x = threadIdx.x + blockIdx.x * blockDim.x;
int y = threadIdx.y + blockIdx.y * blockDim.y;
int offset = x + y * blockDim.x * gridDim.x;
if (offset < RES_X * RES_Y)
{
dev_vfb[offset] = getColorForPixel();
}
}
extern "C" callKernels(Color* dev_vfb)
{
dim3 threadsPerBlock(32, 32)
dim3 blocks(screenWidth / threadsPerBlock.x, screenHeight / threadsPerBlock.y);
kernel<<<blocks, threadsPerBlock>>>(dev_vfb);
}
содержимое дисплея (vfb):
void display(Color vfb[VFB_MAX_SIZE][VFB_MAX_SIZE])
{
// screen is pointer to SDL_Surface
int rs = screen->format->Rshift;
int gs = screen->format->Gshift;
int bs = screen->format->Bshift;
for (int y = 0; y < screen->h; ++y)
{
Uint32* row = (Uint32*) ((Uint8*) screen->pixels + y * screen->pitch);
for (int x = 0; x < screen->w; ++x)
row[x] = vfb[y][x].toRGB32(rs, gs, bs);
}
SDL_Flip(screen);
}
Это простой пример того, что я делаю в своем проекте. Это трассировщик лучей, и, возможно, SDL — худший выбор для взаимодействия с CUDA, но я не знаю, успею ли я его изменить.