void MWC64XSeedGenerator::generateRandomSeeds(Buffer<uvec2>* buffer, unsigned int seed, bool useGLSharing /*= true*/, size_t localWorkGroupSize /*= 256*/) {
    if (kernel_ == NULL) {
        return;
    }

    srand(seed);
    // MWC64X random number generator
    BufferRAM* bufferRAM = buffer->getEditableRepresentation<BufferRAM>();
    uvec2* randomNumbers = static_cast<uvec2*>(bufferRAM->getData());
    int nRandomSeeds = static_cast<int>(bufferRAM->getSize());

    for (int i = 0; i < nRandomSeeds; ++i) {
        randomNumbers[i].x = static_cast<cl_uint>(rand());
    }
    // Data will be transferred to OpenCL device before new representation is returned.
    if (useGLSharing) {
        SyncCLGL glSync;
        BufferCLGL* randomSeedBufferCL = buffer->getEditableRepresentation<BufferCLGL>();
        glSync.addToAquireGLObjectList(randomSeedBufferCL);
        glSync.aquireAllObjects();
        generateSeeds(randomSeedBufferCL, nRandomSeeds, localWorkGroupSize);
    } else {
        BufferCLBase* randomSeedBufferCL = buffer->getEditableRepresentation<BufferCL>();
        generateSeeds(randomSeedBufferCL, nRandomSeeds, localWorkGroupSize);
    }
}
void DirectionalLightSamplerCL::sampleLightSource(const Mesh* mesh, LightSamples& lightSamplesOut, const VECTOR_CLASS<cl::Event>* waitForEvents /*= nullptr*/, cl::Event* event /*= nullptr*/) {
    const LightSource* light = lightSource_.get();
    const BufferRAMPrecision<vec3>* vertices = dynamic_cast<const BufferRAMPrecision<vec3>*>(mesh->getBuffer(0)->getRepresentation<BufferRAM>());
    if (vertices == nullptr || sampleGenerator_ == nullptr) {
        return ;
    }
    if (samples_.getSize() != lightSamplesOut.getSize()) {
        samples_.setSize(lightSamplesOut.getSize());
    }
    std::vector<cl::Event> sampleGenEvents(1);
    sampleGenerator_->setUseGLSharing(false);
    sampleGenerator_->generateNextSamples(samples_, waitForEvents, &sampleGenEvents[0]);

    //const DirectionalLight* light = lights_.getData().get();
    PackedLightSource lightBase = baseLightToPackedLight(light, 1.f, mesh->getCoordinateTransformer().getWorldToDataMatrix());

    vec3 lightDirection = glm::normalize((lightBase.tm * vec4(0.f, 0.f, 1.f, 0.f)).xyz());
    vec3 u, v;
    vec3 lightOrigin{ (lightBase.tm*vec4(0.f, 0.f, 0.f, 1.f)).xyz() };

    std::tie(lightOrigin, u, v) = geometry::fitPlaneAlignedOrientedBoundingBox2D(*vertices->getDataContainer(), Plane(lightOrigin.xyz(), lightDirection.xyz()));

    float area = glm::length(u) * glm::length(v);
    //LogInfo("Bounding box center: " << lightOrigin + 0.5f*(u + v));
    //LogInfo("direction, o, lightU, lightV:" << lightDirection << o << u << v);
    bool useGLSharing = true;
    IVW_OPENCL_PROFILING(profilingEvent, "Light sampling")
        //IVW_OPENCL_PROFILING(intersectionEvent, "Intersection computation")
        try {
        auto samplesCL = samples_.getRepresentation<BufferCL>();
        if (useGLSharing) {
            SyncCLGL glSync;
            
            BufferCLGL* lightSamplesCL = lightSamplesOut.getLightSamples()->getEditableRepresentation<BufferCLGL>();
            // Acquire shared representations before using them in OpenGL
            // The SyncCLGL object will take care of synchronization between OpenGL and OpenCL
            glSync.addToAquireGLObjectList(lightSamplesCL);
            glSync.aquireAllObjects();

            sampleLightSource(samplesCL, lightBase.radiance.xyz(), lightDirection, lightOrigin, u, v, area, samples_.getSize(), lightSamplesCL, &sampleGenEvents, profilingEvent);

        } else {
            BufferCL* lightSamplesCL = lightSamplesOut.getLightSamples()->getEditableRepresentation<BufferCL>();

            sampleLightSource(samplesCL, lightBase.radiance.xyz(), lightDirection, lightOrigin, u, v, area, samples_.getSize(), lightSamplesCL, &sampleGenEvents, profilingEvent);
        }

    } catch (cl::Error& err) {
        LogError(getCLErrorString(err));
    };
    lightSamplesOut.advanceIteration();

}
bool RunningImageMeanAndStandardDeviationCL::computeMeanAndStandardDeviation(const Layer* newSamples, int iteration, Layer*& outMean, Layer*& outStandardDeviation, bool useGLSharing, const VECTOR_CLASS<cl::Event> *waitForEvents, cl::Event *event) {
    if (kernel_ == nullptr) {
        return false;
    }
    if (glm::any(glm::notEqual(newSamples->getDimensions(), standardDeviation_[0].getDimensions()))) {
        standardDeviation_[0].setDimensions(newSamples->getDimensions());
        standardDeviation_[1].setDimensions(newSamples->getDimensions());
        mean_[0].setDimensions(newSamples->getDimensions());
        mean_[1].setDimensions(newSamples->getDimensions());
    }

    //IVW_OPENCL_PROFILING(profilingEvent, "")
    int prevStdId = pingPongIndex_;
    int nextStdId = (pingPongIndex_ + 1) % 2;
    try {
        if (useGLSharing) {
            SyncCLGL glSync;
            
            const LayerCLGL* samples = newSamples->getRepresentation<LayerCLGL>();
            LayerCLGL* prevMeanCL = mean_[prevStdId].getEditableRepresentation<LayerCLGL>();
            LayerCLGL* nextMeanCL = mean_[nextStdId].getEditableRepresentation<LayerCLGL>();
            LayerCLGL* prevStandardDeviation = standardDeviation_[prevStdId].getEditableRepresentation<LayerCLGL>();
            LayerCLGL* nextStandardDeviation = standardDeviation_[nextStdId].getEditableRepresentation<LayerCLGL>();

            // Acquire shared representations before using them in OpenGL
            // The SyncCLGL object will take care of synchronization between OpenGL and OpenCL
            glSync.addToAquireGLObjectList(samples);
            glSync.addToAquireGLObjectList(prevMeanCL);
            glSync.addToAquireGLObjectList(nextMeanCL);
            glSync.addToAquireGLObjectList(prevStandardDeviation);
            glSync.addToAquireGLObjectList(nextStandardDeviation);

            glSync.aquireAllObjects();
            computeMeanAndStandardDeviation(newSamples->getDimensions(), samples, iteration, prevMeanCL, nextMeanCL, prevStandardDeviation, nextStandardDeviation, workGroupSize_, waitForEvents, event);
        } else {
            LayerCL* prevMeanCL = mean_[prevStdId].getEditableRepresentation<LayerCL>();
            LayerCL* nextMeanCL = mean_[nextStdId].getEditableRepresentation<LayerCL>();
            const LayerCL* samples = newSamples->getRepresentation<LayerCL>();
            LayerCL* prevStandardDeviation = standardDeviation_[prevStdId].getEditableRepresentation<LayerCL>();
            LayerCL* nextStandardDeviation = standardDeviation_[nextStdId].getEditableRepresentation<LayerCL>();
            computeMeanAndStandardDeviation(newSamples->getDimensions(), samples, iteration, prevMeanCL, nextMeanCL, prevStandardDeviation, nextStandardDeviation, workGroupSize_, waitForEvents, event);
        }
    } catch (cl::Error& err) {
        LogError(getCLErrorString(err));
        return false;
    }
    pingPongIndex_ = nextStdId;

    outMean = &mean_[nextStdId];
    outStandardDeviation = &standardDeviation_[nextStdId];
    return true;
}
Exemplo n.º 4
0
void BufferCLGL2CLConverter::update(std::shared_ptr<const BufferCLGL> src,
                                    std::shared_ptr<BufferCL> dst) const {
    if (src->getSize() != dst->getSize()) {
        dst->setSize(src->getSize());
    }

    {
        SyncCLGL glSync;
        glSync.addToAquireGLObjectList(src.get());
        glSync.aquireAllObjects();
        OpenCL::getPtr()->getQueue().enqueueCopyBuffer(src->get(), dst->get(), 0, 0,
                                                       src->getSize() * src->getSizeOfElement());
    }
}
Exemplo n.º 5
0
std::shared_ptr<BufferCL> BufferCLGL2CLConverter::createFrom(
    std::shared_ptr<const BufferCLGL> src) const {
    size_t size = src->getSize();
    auto destination =
        std::make_shared<BufferCL>(size, src->getDataFormat(), src->getBufferUsage());
    {
        SyncCLGL glSync;
        glSync.addToAquireGLObjectList(src.get());
        glSync.aquireAllObjects();
        OpenCL::getPtr()->getQueue().enqueueCopyBuffer(src->get(), destination->get(), 0, 0,
                                                       src->getSize() * src->getSizeOfElement());
    }
    return destination;
}
Exemplo n.º 6
0
void VolumeCLGL2CLConverter::update(std::shared_ptr<const VolumeCLGL> volumeSrc,
                                    std::shared_ptr<VolumeCL> volumeDst) const {
    if (volumeSrc->getDimensions() != volumeDst->getDimensions()) {
        volumeDst->setDimensions(volumeSrc->getDimensions());
    }

    {
        SyncCLGL glSync;
        glSync.addToAquireGLObjectList(volumeSrc.get());
        glSync.aquireAllObjects();
        OpenCL::getPtr()->getQueue().enqueueCopyImage(volumeSrc->get(), volumeDst->get(),
                                                      glm::size3_t(0), glm::size3_t(0),
                                                      glm::size3_t(volumeSrc->getDimensions()));
    }
}
Exemplo n.º 7
0
std::shared_ptr<VolumeCL> VolumeCLGL2CLConverter::createFrom(
    std::shared_ptr<const VolumeCLGL> volumeCLGL) const {
#ifdef IVW_DEBUG
    LogWarn("Performance warning: Use shared CLGL representation instead of CL ");
#endif
    const size3_t dimensions{volumeCLGL->getDimensions()};
    auto destination = std::make_shared<VolumeCL>(dimensions, volumeCLGL->getDataFormat());
    {
        SyncCLGL glSync;
        glSync.addToAquireGLObjectList(volumeCLGL.get());
        glSync.aquireAllObjects();
        OpenCL::getPtr()->getQueue().enqueueCopyImage(volumeCLGL->get(), destination->get(),
                                                      glm::size3_t(0), glm::size3_t(0),
                                                      glm::size3_t(dimensions));
    }
    return destination;
}
Exemplo n.º 8
0
bool LayerCLGL::copyRepresentationsTo(DataRepresentation* targetRep) const {
    // ivwAssert(false, "Not implemented");
    // Make sure that the OpenCL layer is deleted before resizing the texture
    // TODO: Implement copying in addition to the resizing
    LayerCLGL* target = dynamic_cast<LayerCLGL*>(targetRep);
    const LayerCLGL* source = this;
    try {
        SyncCLGL glSync;
        glSync.addToAquireGLObjectList(target);
        glSync.addToAquireGLObjectList(source);
        glSync.aquireAllObjects();
        LayerCLResizer::resize(source->get(), target->get(), target->getDimensions());
    } catch (cl::Error err) {
        LogError(getCLErrorString(err));
        return false;
    }
    return true;
}
void UniformSampleGenerator2DCL::generateNextSamples(SampleBuffer& positionSamplesOut, const VECTOR_CLASS<cl::Event>* waitForEvents /*= nullptr*/, cl::Event* event /*= nullptr*/) {
    if (kernel_ == NULL) {
        return throw Exception("Invalid kernel: Kernel not found or failed to compile");
    }
    size2_t nSamples{static_cast<size_t>(std::sqrt(static_cast<double>(positionSamplesOut.getSize())))};
    if (getUseGLSharing()) {
        SyncCLGL glSync;
        BufferCLGL* samples = positionSamplesOut.getEditableRepresentation<BufferCLGL>();

        // Acquire shared representations before using them in OpenGL
        // The SyncCLGL object will take care of synchronization between OpenGL and OpenCL
        glSync.addToAquireGLObjectList(samples);
        glSync.aquireAllObjects();
        generateSamples(nSamples, positionSamplesOut.getSize(), samples, waitForEvents, event);
    } else {
        BufferCL* samples = positionSamplesOut.getEditableRepresentation<BufferCL>();
        generateSamples(nSamples, positionSamplesOut.getSize(), samples, waitForEvents, event);
    }
}
Exemplo n.º 10
0
void VolumeRaycasterCL::volumeRaycast(const Volume* volume, const Layer* entryPoints,
                                      const Layer* exitPoints, const Layer* transferFunction,
                                      Layer* outImage,
                                      const VECTOR_CLASS<cl::Event>* waitForEvents /*= nullptr*/,
                                      cl::Event* event /*= nullptr*/) {
    size2_t localWorkGroupSize(workGroupSize_);
    size2_t globalWorkGroupSize(getGlobalWorkGroupSize(outputSize_.x, localWorkGroupSize.x),
                                getGlobalWorkGroupSize(outputSize_.y, localWorkGroupSize.y));

    if (useGLSharing_) {
        // SyncCLGL will synchronize with OpenGL upon creation and destruction
        SyncCLGL glSync;
        const LayerCLGL* entryCL = entryPoints->getRepresentation<LayerCLGL>();
        const LayerCLGL* exitCL = exitPoints->getRepresentation<LayerCLGL>();
        LayerCLGL* outImageCL = outImage->getEditableRepresentation<LayerCLGL>();
        const VolumeCLGL* volumeCL = volume->getRepresentation<VolumeCLGL>();
        const LayerCLGL* transferFunctionCL = transferFunction->getRepresentation<LayerCLGL>();
        const LayerCLBase* background;
        if (background_) {
            background = background_->getRepresentation<LayerCLGL>();
            glSync.addToAquireGLObjectList(static_cast<const LayerCLGL*>(background));
        } else {
            background = defaultBackground_.getRepresentation<LayerCL>();
        }
        // Shared objects must be acquired before use.
        glSync.addToAquireGLObjectList(entryCL);
        glSync.addToAquireGLObjectList(exitCL);
        glSync.addToAquireGLObjectList(outImageCL);
        glSync.addToAquireGLObjectList(volumeCL);
        glSync.addToAquireGLObjectList(transferFunctionCL);

        // Acquire all of the objects at once
        glSync.aquireAllObjects();

        volumeRaycast(volume, volumeCL, background, entryCL, exitCL, transferFunctionCL, outImageCL,
                      globalWorkGroupSize, localWorkGroupSize, waitForEvents, event);
    } else {
        const LayerCL* entryCL = entryPoints->getRepresentation<LayerCL>();
        const LayerCL* exitCL = exitPoints->getRepresentation<LayerCL>();
        LayerCL* outImageCL = outImage->getEditableRepresentation<LayerCL>();
        const VolumeCL* volumeCL = volume->getRepresentation<VolumeCL>();
        const LayerCL* transferFunctionCL = transferFunction->getRepresentation<LayerCL>();
        // const LayerCL* background = background_->getRepresentation<LayerCL>();
        const LayerCL* background;
        if (background_) {
            background = background_->getRepresentation<LayerCL>();
        } else {
            background = defaultBackground_.getRepresentation<LayerCL>();
        }
        volumeRaycast(volume, volumeCL, background, entryCL, exitCL, transferFunctionCL, outImageCL,
                      globalWorkGroupSize, localWorkGroupSize, waitForEvents, event);
    }
}
void VolumeMaxCLProcessor::process() {
    if (!kernel_) return;
    auto volume = inport_.getData();

    const size3_t dim{volume->getDimensions()};
    const size3_t outDim{glm::ceil(vec3(dim) / static_cast<float>(volumeRegionSize_.get()))};
    // const DataFormatBase* volFormat = inport_.getData()->getDataFormat(); // Not used

    if (!volumeOut_ || volumeOut_->getDimensions() != outDim) {
        volumeOut_ = std::make_shared<Volume>(outDim, DataUInt8::get());
        // volumeOut_ = std::unique_ptr<Volume>( new Volume(outDim, DataUInt32::get()) );
        // volumeOut_ = std::unique_ptr<Volume>( new Volume(outDim, DataFloat32::get()) );
        // Use same transformation to make sure that they are render at the same location
        volumeOut_->setModelMatrix(volume->getModelMatrix());
        volumeOut_->setWorldMatrix(volume->getWorldMatrix());
        outport_.setData(volumeOut_);
    }

    size3_t localWorkGroupSize(workGroupSize_.get());
    size3_t globalWorkGroupSize(getGlobalWorkGroupSize(outDim.x, localWorkGroupSize.x),
                                getGlobalWorkGroupSize(outDim.y, localWorkGroupSize.y),
                                getGlobalWorkGroupSize(outDim.z, localWorkGroupSize.z));

    if (useGLSharing_.get()) {
        SyncCLGL glSync;
        const VolumeCLGL* volumeCL = volume->getRepresentation<VolumeCLGL>();
        VolumeCLGL* volumeOutCL = volumeOut_->getEditableRepresentation<VolumeCLGL>();

        glSync.addToAquireGLObjectList(volumeCL);
        glSync.addToAquireGLObjectList(volumeOutCL);
        glSync.aquireAllObjects();

        executeVolumeOperation(volume.get(), volumeCL, volumeOutCL, outDim, globalWorkGroupSize,
                               localWorkGroupSize);
    } else {
        const VolumeCL* volumeCL = volume->getRepresentation<VolumeCL>();
        VolumeCL* volumeOutCL = volumeOut_->getEditableRepresentation<VolumeCL>();
        executeVolumeOperation(volume.get(), volumeCL, volumeOutCL, outDim, globalWorkGroupSize,
                               localWorkGroupSize);
    }
}
void UniformSampleGenerator2DCL::generateNextSamples(SampleBuffer& positionSamplesOut, SampleBuffer& directionSamplesOut, const VECTOR_CLASS<cl::Event>* waitForEvents /*= nullptr*/, cl::Event* event /*= nullptr*/) {
    cl::Event positionSampleEvent;
    generateNextSamples(positionSamplesOut, waitForEvents, &positionSampleEvent);
    std::vector<cl::Event> waitFor{ 1, positionSampleEvent };
    if (getUseGLSharing()) {
        SyncCLGL glSync;
        auto src = positionSamplesOut.getRepresentation<BufferCLGL>();
        auto dst = directionSamplesOut.getEditableRepresentation<BufferCLGL>();
        // Acquire shared representations before using them in OpenGL
        // The SyncCLGL object will take care of synchronization between OpenGL and OpenCL
        glSync.addToAquireGLObjectList(src);
        glSync.addToAquireGLObjectList(dst);
        glSync.aquireAllObjects();
        OpenCL::getPtr()->getQueue().enqueueCopyBuffer(src->get(), dst->get(), 0, 0,
            src->getSize() * src->getSizeOfElement(), &waitFor, event);
    } else {
        auto src = positionSamplesOut.getRepresentation<BufferCL>();
        auto dst = directionSamplesOut.getEditableRepresentation<BufferCL>();
        OpenCL::getPtr()->getQueue().enqueueCopyBuffer(src->get(), dst->get(), 0, 0,
            src->getSize() * src->getSizeOfElement(), &waitFor, event);
    }

}
void GrayscaleCLProcessor::process() {
    if (kernel_ == nullptr) {
        return;
    }

    auto outImage = outport_.getEditableData();

    // outImage->resize(inImage->getDimensions());
    uvec2 outportDim = outImage->getDimensions();
    auto inImage = input_.getData();
    try {
        if (useGLSharing_.get()) {
            SyncCLGL glSync;

            const ImageCLGL* colorImageCL = inImage->getRepresentation<ImageCLGL>();
            ImageCLGL* outImageCL = outImage->getEditableRepresentation<ImageCLGL>();
            glSync.addToAquireGLObjectList(colorImageCL);
            glSync.addToAquireGLObjectList(outImageCL);
            glSync.aquireAllObjects();
            cl_uint arg = 0;
            kernel_->setArg(arg++, *colorImageCL);
            kernel_->setArg(arg++, *outImageCL);
            OpenCL::getPtr()->getQueue().enqueueNDRangeKernel(
                *kernel_, cl::NullRange, static_cast<glm::size2_t>(outportDim));
        } else {
            const ImageCL* colorImageCL = inImage->getRepresentation<ImageCL>();
            ImageCL* outImageCL = outImage->getEditableRepresentation<ImageCL>();
            cl_uint arg = 0;
            kernel_->setArg(arg++, *colorImageCL);
            kernel_->setArg(arg++, *outImageCL);
            OpenCL::getPtr()->getQueue().enqueueNDRangeKernel(
                *kernel_, cl::NullRange, static_cast<glm::size2_t>(outportDim));
        }
    } catch (cl::Error& err) {
        LogError(getCLErrorString(err));
    }
}
void MWC64XRandomNumberGenerator::generate(Buffer<float>& randomNumbersOut, const VECTOR_CLASS<cl::Event>* waitForEvents /*= nullptr*/, cl::Event* event /*= nullptr*/) {
    if (randomNumbersOut.getSize() != randomState_.getSize()) {
        randomState_.setSize(randomNumbersOut.getSize());

        MWC64XSeedGenerator seedGenerator;
        seedGenerator.generateRandomSeeds(&randomState_, seed_, false);
    }

    BufferCL* rndState = randomState_.getEditableRepresentation<BufferCL>();
    if (useGLSharing_) {
        SyncCLGL glSync;
        BufferCLGL* data = randomNumbersOut.getEditableRepresentation<BufferCLGL>();
        // Acquire shared representations before using them in OpenGL
        // The SyncCLGL object will take care of synchronization between OpenGL and OpenCL
        glSync.addToAquireGLObjectList(data);
        glSync.aquireAllObjects();
        generateNumbers(rndState, data, waitForEvents, event);
    } else {
        BufferCL* data = randomNumbersOut.getEditableRepresentation<BufferCL>();
        generateNumbers(rndState, data, waitForEvents, event);


    }
}
Exemplo n.º 15
0
bool MeshEntryExitPointsCL::computeEntryExitPoints(
    const Mesh* mesh, const mat4& worldToView, const mat4& viewToClip, Layer* entryPoints,
    Layer* exitPoints, bool useGLSharing,
    const VECTOR_CLASS<cl::Event>* waitForEvents /*= nullptr*/, cl::Event* event /*= nullptr*/) {
    if (kernel_ == nullptr) {
        return false;
    }
    // the rendered plane is specified in camera coordinates
    // thus we must transform from camera to world to texture coordinates
    mat4 worldToTexMat = mesh->getCoordinateTransformer().getWorldToDataMatrix();
    uvec2 outportDim = entryPoints->getDimensions();
    mat4 NDCToTextureMat = worldToTexMat * glm::inverse(worldToView) * glm::inverse(viewToClip);

    int nIndices = static_cast<int>(mesh->getIndicies(0)->getSize());
    if (useGLSharing) {
        SyncCLGL glSync;
        LayerCLGL* entryCL = entryPoints->getEditableRepresentation<LayerCLGL>();
        LayerCLGL* exitCL = exitPoints->getEditableRepresentation<LayerCLGL>();
        const BufferCLGL* vertices = mesh->getAttributes(0)->getRepresentation<BufferCLGL>();
        const BufferCLGL* indices = mesh->getIndicies(0)->getRepresentation<ElementBufferCLGL>();
        glSync.addToAquireGLObjectList(entryCL);
        glSync.addToAquireGLObjectList(exitCL);
        glSync.addToAquireGLObjectList(vertices);
        glSync.addToAquireGLObjectList(indices);
        glSync.aquireAllObjects();

        computeEntryExitPoints(NDCToTextureMat, worldToTexMat, vertices, indices, nIndices, entryCL,
                               exitCL, outportDim, waitForEvents, event);
    } else {
        LayerCL* entryCL = entryPoints->getEditableRepresentation<LayerCL>();
        LayerCL* exitCL = exitPoints->getEditableRepresentation<LayerCL>();
        const BufferCL* vertices = mesh->getAttributes(0)->getRepresentation<BufferCL>();
        const BufferCL* indices = mesh->getIndicies(0)->getRepresentation<ElementBufferCL>();
        computeEntryExitPoints(NDCToTextureMat, worldToTexMat, vertices, indices, nIndices, entryCL,
                               exitCL, outportDim, waitForEvents, event);
    }

    return true;
}
void PhotonTracerCL::tracePhotons(const Volume* volume, const TransferFunction& transferFunction, const BufferCL* axisAlignedBoundingBoxCL, const AdvancedMaterialProperty& material, const Camera* camera, float stepSize, const LightSamples* lightSamples, const Buffer<unsigned int>* photonsToRecomputeIndices, int nInvalidPhotons, int photonOffset, int batch, int maxInteractions, PhotonData* photonOutData, const VECTOR_CLASS<cl::Event> *waitForEvents, cl::Event *event /*= nullptr*/) {
    if (!photonTracerKernel_) {
        return;
    }
    if (randomState_.getSize() != photonOutData->getNumberOfPhotons()) {
        setRandomSeedSize(photonOutData->getNumberOfPhotons());
    }
    auto volumeDim = volume->getDimensions();
    // Texture space spacing
    const mat4 volumeTextureToWorld = volume->getCoordinateTransformer().getTextureToWorldMatrix();
    const mat4 textureToIndexMatrix = volume->getCoordinateTransformer().getTextureToIndexMatrix();
    vec3 voxelSpacing(1.f / glm::length(textureToIndexMatrix[0]), 1.f / glm::length(textureToIndexMatrix[1]), 1.f / glm::length(textureToIndexMatrix[2]));
    try {
        if (useGLSharing_) {
            
            SyncCLGL glSync;
            auto volumeCL = volume->getRepresentation<VolumeCLGL>();
            const BufferCLGL* lightSamplesCL = lightSamples->getLightSamples()->getRepresentation<BufferCLGL>();
            const BufferCLGL* intersectionPointsCL = lightSamples->getIntersectionPoints()->getRepresentation<BufferCLGL>();
            BufferCLGL* photonCL = photonOutData->photons_.getEditableRepresentation<BufferCLGL>();
            
            const LayerCLGL* transferFunctionCL = transferFunction.getData()->getRepresentation<LayerCLGL>();
            const ElementBufferCLGL* photonsToRecomputeIndicesCL = nullptr;
            
            // Acquire shared representations before using them in OpenGL
            // The SyncCLGL object will take care of synchronization between OpenGL and OpenCL
            glSync.addToAquireGLObjectList(volumeCL);
            glSync.addToAquireGLObjectList(lightSamplesCL);
            glSync.addToAquireGLObjectList(intersectionPointsCL);
            glSync.addToAquireGLObjectList(photonCL);
            glSync.addToAquireGLObjectList(transferFunctionCL);
            //{IVW_CPU_PROFILING("aquireAllObjects")
            if (photonsToRecomputeIndices) {
                photonsToRecomputeIndicesCL = photonsToRecomputeIndices->getRepresentation<ElementBufferCLGL>();
                glSync.addToAquireGLObjectList(photonsToRecomputeIndicesCL);
            }

            
            glSync.aquireAllObjects();
            //}
            //{IVW_CPU_PROFILING("tracePhotons")
                tracePhotons(photonOutData, volumeCL, volumeCL->getVolumeStruct(volume), axisAlignedBoundingBoxCL
                , transferFunctionCL, material, stepSize, lightSamplesCL, intersectionPointsCL, lightSamples->getSize(), photonsToRecomputeIndicesCL, nInvalidPhotons
                , photonCL, photonOffset, batch, maxInteractions
                , waitForEvents, event);
            //}
        } else {
            const VolumeCL* volumeCL = volume->getRepresentation<VolumeCL>();
            const BufferCL* lightSamplesCL = lightSamples->getLightSamples()->getRepresentation<BufferCL>();
            const BufferCL* intersectionPointsCL = lightSamples->getIntersectionPoints()->getRepresentation<BufferCL>();
            BufferCL* photonCL = photonOutData->photons_.getEditableRepresentation<BufferCL>();
            const LayerCL* transferFunctionCL = transferFunction.getData()->getRepresentation<LayerCL>();
            const BufferCL* photonsToRecomputeIndicesCL = nullptr;
            if (photonsToRecomputeIndices) {
                photonsToRecomputeIndicesCL = photonsToRecomputeIndices->getRepresentation<BufferCL>();
            }
            tracePhotons(photonOutData, volumeCL, volumeCL->getVolumeStruct(volume), axisAlignedBoundingBoxCL
                , transferFunctionCL, material, stepSize, lightSamplesCL, intersectionPointsCL, lightSamples->getSize(), photonsToRecomputeIndicesCL, nInvalidPhotons
                , photonCL, photonOffset, batch, maxInteractions
                , waitForEvents, event);
        }
    } catch (cl::Error& err) {
        LogError(getCLErrorString(err));
    }

}