void PathOCLRenderThread::InitFrameBuffer() { //-------------------------------------------------------------------------- // FrameBuffer definition //-------------------------------------------------------------------------- frameBufferPixelCount = (renderEngine->film->GetWidth() + 2) * (renderEngine->film->GetHeight() + 2); // Delete previous allocated frameBuffer delete[] frameBuffer; frameBuffer = new PathOCL::Pixel[frameBufferPixelCount]; for (unsigned int i = 0; i < frameBufferPixelCount; ++i) { frameBuffer[i].c.r = 0.f; frameBuffer[i].c.g = 0.f; frameBuffer[i].c.b = 0.f; frameBuffer[i].count = 0.f; } AllocOCLBufferRW(&frameBufferBuff, sizeof(PathOCL::Pixel) * frameBufferPixelCount, "FrameBuffer"); delete[] alphaFrameBuffer; alphaFrameBuffer = NULL; // Check if the film has an alpha channel if (renderEngine->film->IsAlphaChannelEnabled()) { alphaFrameBuffer = new PathOCL::AlphaPixel[frameBufferPixelCount]; for (unsigned int i = 0; i < frameBufferPixelCount; ++i) alphaFrameBuffer[i].alpha = 0.f; AllocOCLBufferRW(&alphaFrameBufferBuff, sizeof(PathOCL::AlphaPixel) * frameBufferPixelCount, "Alpha Channel FrameBuffer"); } }
void PathOCLRenderThread::InitFrameBuffer() { //-------------------------------------------------------------------------- // FrameBuffer definition //-------------------------------------------------------------------------- frameBufferPixelCount = (renderEngine->film->GetWidth() + 2) * (renderEngine->film->GetHeight() + 2); // Delete previous allocated frameBuffer delete[] frameBuffer; frameBuffer = new PathOCL::Pixel[frameBufferPixelCount]; for (unsigned int i = 0; i < frameBufferPixelCount; ++i) { frameBuffer[i].c.r = 0.f; frameBuffer[i].c.g = 0.f; frameBuffer[i].c.b = 0.f; frameBuffer[i].count = 0.f; } AllocOCLBufferRW(&frameBufferBuff, sizeof(PathOCL::Pixel) * frameBufferPixelCount, "FrameBuffer"); }
OCLRendererThread::OCLRendererThread(const size_t threadIndex, OCLRenderer *renderer, cl::Device device) : index(threadIndex), renderer(renderer), dev(device), usedDeviceMemory(0) { const GameLevel &gameLevel(*(renderer->gameLevel)); const unsigned int width = gameLevel.gameConfig->GetScreenWidth(); const unsigned int height = gameLevel.gameConfig->GetScreenHeight(); const CompiledScene &compiledScene(*(renderer->compiledScene)); if (renderer->renderThread.size() > 1) cpuFrameBuffer = new FrameBuffer(width, height); else cpuFrameBuffer = NULL; //-------------------------------------------------------------------------- // OpenCL setup //-------------------------------------------------------------------------- // Allocate a context with the selected device VECTOR_CLASS<cl::Device> devices; devices.push_back(dev); cl::Platform platform = dev.getInfo<CL_DEVICE_PLATFORM>(); // The first thread uses OpenCL/OpenGL interoperability if (index == 0) { #if defined (__APPLE__) CGLContextObj kCGLContext = CGLGetCurrentContext(); CGLShareGroupObj kCGLShareGroup = CGLGetShareGroup(kCGLContext); cl_context_properties cps[] = { CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE, (cl_context_properties)kCGLShareGroup, 0 }; #else #ifdef WIN32 cl_context_properties cps[] = { CL_GL_CONTEXT_KHR, (intptr_t)wglGetCurrentContext(), CL_WGL_HDC_KHR, (intptr_t)wglGetCurrentDC(), CL_CONTEXT_PLATFORM, (cl_context_properties)platform(), 0 }; #else cl_context_properties cps[] = { CL_GL_CONTEXT_KHR, (intptr_t)glXGetCurrentContext(), CL_GLX_DISPLAY_KHR, (intptr_t)glXGetCurrentDisplay(), CL_CONTEXT_PLATFORM, (cl_context_properties)platform(), 0 }; #endif #endif ctx = new cl::Context(devices, cps); } else ctx = new cl::Context(devices); // Allocate the queue for this device cmdQueue = new cl::CommandQueue(*ctx, dev); //-------------------------------------------------------------------------- // Allocate the buffers //-------------------------------------------------------------------------- passFrameBuffer = NULL; tmpFrameBuffer = NULL; frameBuffer = NULL; toneMapFrameBuffer = NULL; bvhBuffer = NULL; gpuTaskBuffer = NULL; cameraBuffer = NULL; infiniteLightBuffer = NULL; matBuffer = NULL; matIndexBuffer = NULL; texMapBuffer = NULL; texMapRGBBuffer = NULL; texMapInstanceBuffer = NULL; bumpMapInstanceBuffer = NULL; AllocOCLBufferRW(&passFrameBuffer, sizeof(Pixel) * width * height, "Pass FrameBuffer"); AllocOCLBufferRW(&tmpFrameBuffer, sizeof(Pixel) * width * height, "Temporary FrameBuffer"); if (index == 0) { AllocOCLBufferRW(&frameBuffer, sizeof(Pixel) * width * height, "FrameBuffer"); AllocOCLBufferRW(&toneMapFrameBuffer, sizeof(Pixel) * width * height, "ToneMap FrameBuffer"); } AllocOCLBufferRW(&gpuTaskBuffer, sizeof(ocl_kernels::GPUTask) * width * height, "GPUTask"); AllocOCLBufferRO(&cameraBuffer, sizeof(compiledscene::Camera), "Camera"); AllocOCLBufferRO(&infiniteLightBuffer, (void *)(gameLevel.scene->infiniteLight->GetTexture()->GetTexMap()->GetPixels()), sizeof(Spectrum) * gameLevel.scene->infiniteLight->GetTexture()->GetTexMap()->GetWidth() * gameLevel.scene->infiniteLight->GetTexture()->GetTexMap()->GetHeight(), "Inifinite Light"); AllocOCLBufferRO(&matBuffer, (void *)(&compiledScene.mats[0]), sizeof(compiledscene::Material) * compiledScene.mats.size(), "Materials"); AllocOCLBufferRO(&matIndexBuffer, (void *)(&compiledScene.sphereMats[0]), sizeof(unsigned int) * compiledScene.sphereMats.size(), "Material Indices"); if (compiledScene.texMaps.size() > 0) { AllocOCLBufferRO(&texMapBuffer, (void *)(&compiledScene.texMaps[0]), sizeof(compiledscene::TexMap) * compiledScene.texMaps.size(), "Texture Maps"); AllocOCLBufferRO(&texMapRGBBuffer, (void *)(compiledScene.rgbTexMem), sizeof(Spectrum) * compiledScene.totRGBTexMem, "Texture Map Images"); AllocOCLBufferRO(&texMapInstanceBuffer, (void *)(&compiledScene.sphereTexs[0]), sizeof(compiledscene::TexMapInstance) * compiledScene.sphereTexs.size(), "Texture Map Instances"); if (compiledScene.sphereBumps.size() > 0) AllocOCLBufferRO(&bumpMapInstanceBuffer, (void *)(&compiledScene.sphereBumps[0]), sizeof(compiledscene::BumpMapInstance) * compiledScene.sphereBumps.size(), "Bump Map Instances"); } SFERA_LOG("[OCLRenderer] Total OpenCL device memory used: " << fixed << setprecision(2) << usedDeviceMemory / (1024 * 1024) << "Mbytes"); if (index == 0) { //-------------------------------------------------------------------------- // Create pixel buffer object for display //-------------------------------------------------------------------------- glGenBuffersARB(1, &pbo); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo); glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, width * height * sizeof(GLubyte) * 4, 0, GL_STREAM_DRAW_ARB); glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); pboBuff = new cl::BufferGL(*ctx, CL_MEM_READ_WRITE, pbo); } //-------------------------------------------------------------------------- // Compile the kernel source //-------------------------------------------------------------------------- // Set #define symbols stringstream ss; ss.precision(6); ss << scientific << " -D PARAM_SCREEN_WIDTH=" << width << " -D PARAM_SCREEN_HEIGHT=" << height << " -D PARAM_SCREEN_SAMPLEPERPASS="******" -D PARAM_RAY_EPSILON=" << EPSILON << "f" << " -D PARAM_MAX_DIFFUSE_BOUNCE=" << gameLevel.maxPathDiffuseBounces << " -D PARAM_MAX_SPECULARGLOSSY_BOUNCE=" << gameLevel.maxPathSpecularGlossyBounces << " -D PARAM_IL_SHIFT_U=" << gameLevel.scene->infiniteLight->GetShiftU() << "f" << " -D PARAM_IL_SHIFT_V=" << gameLevel.scene->infiniteLight->GetShiftV() << "f" << " -D PARAM_IL_GAIN_R=" << gameLevel.scene->infiniteLight->GetGain().r << "f" << " -D PARAM_IL_GAIN_G=" << gameLevel.scene->infiniteLight->GetGain().g << "f" << " -D PARAM_IL_GAIN_B=" << gameLevel.scene->infiniteLight->GetGain().b << "f" << " -D PARAM_IL_MAP_WIDTH=" << gameLevel.scene->infiniteLight->GetTexture()->GetTexMap()->GetWidth() << " -D PARAM_IL_MAP_HEIGHT=" << gameLevel.scene->infiniteLight->GetTexture()->GetTexMap()->GetHeight() << " -D PARAM_GAMMA=" << gameLevel.toneMap->GetGamma() << "f" << " -D PARAM_MEM_TYPE=" << gameLevel.gameConfig->GetOpenCLMemType(); if (compiledScene.enable_MAT_MATTE) ss << " -D PARAM_ENABLE_MAT_MATTE"; if (compiledScene.enable_MAT_MIRROR) ss << " -D PARAM_ENABLE_MAT_MIRROR"; if (compiledScene.enable_MAT_GLASS) ss << " -D PARAM_ENABLE_MAT_GLASS"; if (compiledScene.enable_MAT_METAL) ss << " -D PARAM_ENABLE_MAT_METAL"; if (compiledScene.enable_MAT_ALLOY) ss << " -D PARAM_ENABLE_MAT_ALLOY"; if (texMapBuffer) { ss << " -D PARAM_HAS_TEXTUREMAPS"; if (compiledScene.sphereBumps.size() > 0) ss << " -D PARAM_HAS_BUMPMAPS"; } switch (gameLevel.toneMap->GetType()) { case TONEMAP_REINHARD02: ss << " -D PARAM_TM_LINEAR_SCALE=1.0f"; break; case TONEMAP_LINEAR: { LinearToneMap *tm = (LinearToneMap *)gameLevel.toneMap; ss << " -D PARAM_TM_LINEAR_SCALE=" << tm->scale << "f"; break; } default: assert (false); } #if defined(__APPLE__) ss << " -D __APPLE__"; #endif SFERA_LOG("[OCLRenderer] Defined symbols: " << ss.str()); SFERA_LOG("[OCLRenderer] Compiling kernels"); cl::Program::Sources source(1, std::make_pair(KernelSource_kernel_core.c_str(), KernelSource_kernel_core.length())); cl::Program program = cl::Program(*ctx, source); try { VECTOR_CLASS<cl::Device> buildDevice; buildDevice.push_back(dev); program.build(buildDevice, ss.str().c_str()); } catch (cl::Error err) { cl::STRING_CLASS strError = program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(dev); SFERA_LOG("[OCLRenderer] Kernel compilation error:\n" << strError.c_str()); throw err; } kernelInit = new cl::Kernel(program, "Init"); kernelInit->setArg(0, *gpuTaskBuffer); cmdQueue->enqueueNDRangeKernel(*kernelInit, cl::NullRange, cl::NDRange(RoundUp<unsigned int>(width * height, WORKGROUP_SIZE)), cl::NDRange(WORKGROUP_SIZE)); kernelInitFrameBuffer = new cl::Kernel(program, "InitFB"); if (index == 0) { kernelInitFrameBuffer->setArg(0, *frameBuffer); cmdQueue->enqueueNDRangeKernel(*kernelInitFrameBuffer, cl::NullRange, cl::NDRange(RoundUp<unsigned int>(width * height, WORKGROUP_SIZE)), cl::NDRange(WORKGROUP_SIZE)); } kernelInitFrameBuffer->setArg(0, *passFrameBuffer); kernelPathTracing = new cl::Kernel(program, "PathTracing"); unsigned int argIndex = 0; kernelPathTracing->setArg(argIndex++, *gpuTaskBuffer); argIndex++; kernelPathTracing->setArg(argIndex++, *cameraBuffer); kernelPathTracing->setArg(argIndex++, *infiniteLightBuffer); kernelPathTracing->setArg(argIndex++, *passFrameBuffer); kernelPathTracing->setArg(argIndex++, *matBuffer); kernelPathTracing->setArg(argIndex++, *matIndexBuffer); if (texMapBuffer) { kernelPathTracing->setArg(argIndex++, *texMapBuffer); kernelPathTracing->setArg(argIndex++, *texMapRGBBuffer); kernelPathTracing->setArg(argIndex++, *texMapInstanceBuffer); if (compiledScene.sphereBumps.size() > 0) kernelPathTracing->setArg(argIndex++, *bumpMapInstanceBuffer); } kernelApplyBlurLightFilterXR1 = new cl::Kernel(program, "ApplyBlurLightFilterXR1"); kernelApplyBlurLightFilterXR1->setArg(0, *passFrameBuffer); kernelApplyBlurLightFilterXR1->setArg(1, *tmpFrameBuffer); kernelApplyBlurLightFilterYR1 = new cl::Kernel(program, "ApplyBlurLightFilterYR1"); kernelApplyBlurLightFilterYR1->setArg(0, *tmpFrameBuffer); kernelApplyBlurLightFilterYR1->setArg(1, *passFrameBuffer); kernelApplyBlurHeavyFilterXR1 = new cl::Kernel(program, "ApplyBlurHeavyFilterXR1"); kernelApplyBlurHeavyFilterXR1->setArg(0, *passFrameBuffer); kernelApplyBlurHeavyFilterXR1->setArg(1, *tmpFrameBuffer); kernelApplyBlurHeavyFilterYR1 = new cl::Kernel(program, "ApplyBlurHeavyFilterYR1"); kernelApplyBlurHeavyFilterYR1->setArg(0, *tmpFrameBuffer); kernelApplyBlurHeavyFilterYR1->setArg(1, *passFrameBuffer); kernelApplyBoxFilterXR1 = new cl::Kernel(program, "ApplyBoxFilterXR1"); kernelApplyBoxFilterXR1->setArg(0, *passFrameBuffer); kernelApplyBoxFilterXR1->setArg(1, *tmpFrameBuffer); kernelApplyBoxFilterYR1 = new cl::Kernel(program, "ApplyBoxFilterYR1"); kernelApplyBoxFilterYR1->setArg(0, *tmpFrameBuffer); kernelApplyBoxFilterYR1->setArg(1, *passFrameBuffer); if (index == 0) { kernelBlendFrame = new cl::Kernel(program, "BlendFrame"); kernelBlendFrame->setArg(0, *passFrameBuffer); kernelBlendFrame->setArg(1, *frameBuffer); kernelToneMapLinear = new cl::Kernel(program, "ToneMapLinear"); kernelToneMapLinear->setArg(0, *frameBuffer); kernelToneMapLinear->setArg(1, *toneMapFrameBuffer); kernelUpdatePixelBuffer = new cl::Kernel(program, "UpdatePixelBuffer"); kernelUpdatePixelBuffer->setArg(0, *toneMapFrameBuffer); kernelUpdatePixelBuffer->setArg(1, *pboBuff); } else { kernelBlendFrame = NULL; kernelToneMapLinear = NULL; kernelUpdatePixelBuffer = NULL; } }