<commit_before>// Copyright 2018 The clvk authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <algorithm>

#include "kernel.hpp"
#include "memory.hpp"

cl_ulong cvk_kernel::local_mem_size() const {
    cl_ulong ret = 0; // FIXME take the compile-time allocations into account

    for (uint32_t i = 0; i < m_args.size(); i++) {
        auto const& arg = m_args[i];
        if (arg.kind == kernel_argument_kind::local) {
            ret += m_argument_values->local_arg_size(i);
        }
    }

    return ret;
}

cl_int cvk_kernel::init() {
    cl_int errcode;
    m_entry_point = m_program->get_entry_point(m_name, &errcode);
    if (!m_entry_point) {
        return errcode;
    }

    // Store a copy of the arguments
    m_args = m_entry_point->args();

    // Mark all arguments as unset
    m_args_set.resize(m_args.size(), false);

    // Init argument values
    m_argument_values = cvk_kernel_argument_values::create(m_entry_point);
    if (m_argument_values == nullptr) {
        return CL_OUT_OF_RESOURCES;
    }

    return CL_SUCCESS;
}

VkPipeline
cvk_kernel::create_pipeline(const cvk_spec_constant_map& spec_constants) {
    return m_entry_point->create_pipeline(spec_constants);
}

std::unique_ptr<cvk_kernel> cvk_kernel::clone(cl_int* errcode_ret) const {

    auto kernel = std::make_unique<cvk_kernel>(m_program, m_name.c_str());

    *errcode_ret = kernel->init();

    if (*errcode_ret != CL_SUCCESS) {
        return nullptr;
    }

    kernel->m_argument_values =
        cvk_kernel_argument_values::create(*m_argument_values.get());

    return kernel;
}

cl_int cvk_kernel::set_arg(cl_uint index, size_t size, const void* value) {
    std::lock_guard<std::mutex> lock(m_lock);

    // Clone argument values if they have been used in an enqueue
    if (m_argument_values->is_enqueued()) {
        m_argument_values =
            cvk_kernel_argument_values::create(*m_argument_values);
        if (m_argument_values == nullptr) {
            return CL_OUT_OF_RESOURCES;
        }
    }

    auto const& arg = m_args[index];

    cl_int ret = m_argument_values->set_arg(arg, size, value);

    if (ret == CL_SUCCESS) {
        // Mark argument as set
        m_args_set[index] = true;
    }

    return ret;
}

bool cvk_kernel_argument_values::setup_descriptor_sets() {
    std::lock_guard<std::mutex> lock(m_lock);

    auto program = m_entry_point->program();
    auto dev = program->context()->device()->vulkan_device();

    // Do nothing if these argument values have already been used in an enqueue
    if (m_is_enqueued) {
        return true;
    }

    m_is_enqueued = true;

    // Allocate descriptor sets
    if (!m_entry_point->allocate_descriptor_sets(descriptor_sets())) {
        return false;
    }
    VkDescriptorSet* ds = descriptor_sets();

    // Make enough space to store all descriptor write structures
    size_t max_descriptor_writes =
        m_args.size() // upper bound that includes POD buffers
        + program->literal_sampler_descs().size() +
        1; // module constant data buffer
    std::vector<VkWriteDescriptorSet> descriptor_writes;
    std::vector<VkDescriptorBufferInfo> buffer_info;
    std::vector<VkDescriptorImageInfo> image_info;
    descriptor_writes.reserve(max_descriptor_writes);
    buffer_info.reserve(max_descriptor_writes);
    image_info.reserve(max_descriptor_writes);

    // Setup module-scope variables
    if (program->module_constant_data_buffer() != nullptr) {
        auto buffer = program->module_constant_data_buffer();
        auto info = program->module_constant_data_buffer_info();
        cvk_debug_fn(
            "constant data buffer %p, size = %zu @ set = %u, binding = %u",
            buffer->vulkan_buffer(), buffer->size(), info->set, info->binding);
        // Update descriptors
        VkDescriptorBufferInfo bufferInfo = {buffer->vulkan_buffer(),
                                             0, // offset
                                             VK_WHOLE_SIZE};
        buffer_info.push_back(bufferInfo);

        VkWriteDescriptorSet writeDescriptorSet = {
            VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
            nullptr,
            ds[info->set],
            info->binding,                     // dstBinding
            0,                                 // dstArrayElement
            1,                                 // descriptorCount
            VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // descriptorType
            nullptr,                           // pImageInfo
            &buffer_info.back(),
            nullptr, // pTexelBufferView
        };
        descriptor_writes.push_back(writeDescriptorSet);
    }

    // Setup descriptors for POD arguments
    if (m_entry_point->has_pod_buffer_arguments()) {
        // Create POD buffer
        if (!create_pod_buffer()) {
            return false;
        }

        // Update descriptors
        cvk_debug_fn("pod buffer %p, size = %zu @ set = %u, binding = %u",
                     m_pod_buffer->vulkan_buffer(), m_pod_buffer->size(),
                     m_pod_arg->descriptorSet, m_pod_arg->binding);
        VkDescriptorBufferInfo bufferInfo = {m_pod_buffer->vulkan_buffer(),
                                             0, // offset
                                             VK_WHOLE_SIZE};
        buffer_info.push_back(bufferInfo);

        VkWriteDescriptorSet writeDescriptorSet = {
            VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
            nullptr,
            ds[m_pod_arg->descriptorSet],
            m_pod_arg->binding,                   // dstBinding
            0,                                    // dstArrayElement
            1,                                    // descriptorCount
            m_entry_point->pod_descriptor_type(), // descriptorType
            nullptr,                              // pImageInfo
            &buffer_info.back(),
            nullptr, // pTexelBufferView
        };
        descriptor_writes.push_back(writeDescriptorSet);
    }

    // Setup other kernel argument descriptors
    for (cl_uint i = 0; i < m_args.size(); i++) {
        auto const& arg = m_args[i];

        switch (arg.kind) {

        case kernel_argument_kind::buffer:
        case kernel_argument_kind::buffer_ubo: {
            auto buffer = static_cast<cvk_buffer*>(get_arg_value(arg));
            auto vkbuf = buffer->vulkan_buffer();
            cvk_debug_fn(
                "buffer %p, offset = %zu, size = %zu @ set = %u, binding = %u",
                buffer->vulkan_buffer(), buffer->vulkan_buffer_offset(),
                buffer->size(), arg.descriptorSet, arg.binding);
            VkDescriptorBufferInfo bufferInfo = {
                vkbuf,
                buffer->vulkan_buffer_offset(), // offset
                buffer->size()};
            buffer_info.push_back(bufferInfo);

            auto descriptor_type = arg.kind == kernel_argument_kind::buffer
                                       ? VK_DESCRIPTOR_TYPE_STORAGE_BUFFER
                                       : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
            VkWriteDescriptorSet writeDescriptorSet = {
                VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
                nullptr,
                ds[arg.descriptorSet],
                arg.binding, // dstBinding
                0,           // dstArrayElement
                1,           // descriptorCount
                descriptor_type,
                nullptr, // pImageInfo
                &buffer_info.back(),
                nullptr, // pTexelBufferView
            };
            descriptor_writes.push_back(writeDescriptorSet);
            break;
        }
        case kernel_argument_kind::sampler: {
            auto clsampler = static_cast<cvk_sampler*>(get_arg_value(arg));
            auto sampler = clsampler->vulkan_sampler();

            cvk_debug_fn("sampler %p @ set = %u, binding = %u", sampler,
                         arg.descriptorSet, arg.binding);
            VkDescriptorImageInfo imageInfo = {
                sampler,
                VK_NULL_HANDLE,           // imageView
                VK_IMAGE_LAYOUT_UNDEFINED // imageLayout
            };
            image_info.push_back(imageInfo);

            VkWriteDescriptorSet writeDescriptorSet = {
                VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
                nullptr,
                ds[arg.descriptorSet],
                arg.binding, // dstBinding
                0,           // dstArrayElement
                1,           // descriptorCount
                VK_DESCRIPTOR_TYPE_SAMPLER,
                &image_info.back(), // pImageInfo
                nullptr,            // pBufferInfo
                nullptr,            // pTexelBufferView
            };
            descriptor_writes.push_back(writeDescriptorSet);
            break;
        }
        case kernel_argument_kind::ro_image:
        case kernel_argument_kind::wo_image: {
            auto image = static_cast<cvk_image*>(get_arg_value(arg));

            cvk_debug_fn("image view %p @ set = %u, binding = %u",
                         image->vulkan_image_view(), arg.descriptorSet,
                         arg.binding);
            VkDescriptorImageInfo imageInfo = {
                VK_NULL_HANDLE,
                image->vulkan_image_view(), // imageView
                VK_IMAGE_LAYOUT_GENERAL     // imageLayout
            };
            image_info.push_back(imageInfo);

            VkDescriptorType dtype = arg.kind == kernel_argument_kind::ro_image
                                         ? VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
                                         : VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;

            VkWriteDescriptorSet writeDescriptorSet = {
                VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
                nullptr,
                ds[arg.descriptorSet],
                arg.binding, // dstBinding
                0,           // dstArrayElement
                1,           // descriptorCount
                dtype,
                &image_info.back(), // pImageInfo
                nullptr,            // pBufferInfo
                nullptr,            // pTexelBufferView
            };
            descriptor_writes.push_back(writeDescriptorSet);
            break;
        }
        case kernel_argument_kind::pod: // skip POD arguments
        case kernel_argument_kind::pod_ubo:
        case kernel_argument_kind::pod_pushconstant:
            break;
        case kernel_argument_kind::local: // nothing to do?
            break;
        default:
            cvk_error_fn("unsupported argument type");
            return false;
        }
    }

    // Setup literal samplers
    for (size_t i = 0; i < program->literal_sampler_descs().size(); i++) {
        auto desc = program->literal_sampler_descs()[i];
        auto clsampler = icd_downcast(program->literal_samplers()[i]);
        auto sampler = clsampler->vulkan_sampler();

        VkDescriptorImageInfo imageInfo = {
            sampler,
            VK_NULL_HANDLE,           // imageView
            VK_IMAGE_LAYOUT_UNDEFINED // imageLayout
        };
        image_info.push_back(imageInfo);

        VkWriteDescriptorSet writeDescriptorSet = {
            VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
            nullptr,
            ds[desc.descriptorSet],
            desc.binding, // dstBinding
            0,            // dstArrayElement
            1,            // descriptorCount
            VK_DESCRIPTOR_TYPE_SAMPLER,
            &image_info.back(), // pImageInfo
            nullptr,            // pBufferInfo
            nullptr,            // pTexelBufferView
        };
        descriptor_writes.push_back(writeDescriptorSet);
    }

    // Write descriptors to device
    vkUpdateDescriptorSets(dev, static_cast<uint32_t>(descriptor_writes.size()),
                           descriptor_writes.data(), 0, nullptr);

    return true;
}
<commit_msg>Don't crash when NULL memory objects are used as kernel arguments<commit_after>// Copyright 2018 The clvk authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <algorithm>

#include "kernel.hpp"
#include "memory.hpp"

cl_ulong cvk_kernel::local_mem_size() const {
    cl_ulong ret = 0; // FIXME take the compile-time allocations into account

    for (uint32_t i = 0; i < m_args.size(); i++) {
        auto const& arg = m_args[i];
        if (arg.kind == kernel_argument_kind::local) {
            ret += m_argument_values->local_arg_size(i);
        }
    }

    return ret;
}

cl_int cvk_kernel::init() {
    cl_int errcode;
    m_entry_point = m_program->get_entry_point(m_name, &errcode);
    if (!m_entry_point) {
        return errcode;
    }

    // Store a copy of the arguments
    m_args = m_entry_point->args();

    // Mark all arguments as unset
    m_args_set.resize(m_args.size(), false);

    // Init argument values
    m_argument_values = cvk_kernel_argument_values::create(m_entry_point);
    if (m_argument_values == nullptr) {
        return CL_OUT_OF_RESOURCES;
    }

    return CL_SUCCESS;
}

VkPipeline
cvk_kernel::create_pipeline(const cvk_spec_constant_map& spec_constants) {
    return m_entry_point->create_pipeline(spec_constants);
}

std::unique_ptr<cvk_kernel> cvk_kernel::clone(cl_int* errcode_ret) const {

    auto kernel = std::make_unique<cvk_kernel>(m_program, m_name.c_str());

    *errcode_ret = kernel->init();

    if (*errcode_ret != CL_SUCCESS) {
        return nullptr;
    }

    kernel->m_argument_values =
        cvk_kernel_argument_values::create(*m_argument_values.get());

    return kernel;
}

cl_int cvk_kernel::set_arg(cl_uint index, size_t size, const void* value) {
    std::lock_guard<std::mutex> lock(m_lock);

    // Clone argument values if they have been used in an enqueue
    if (m_argument_values->is_enqueued()) {
        m_argument_values =
            cvk_kernel_argument_values::create(*m_argument_values);
        if (m_argument_values == nullptr) {
            return CL_OUT_OF_RESOURCES;
        }
    }

    auto const& arg = m_args[index];

    cl_int ret = m_argument_values->set_arg(arg, size, value);

    if (ret == CL_SUCCESS) {
        // Mark argument as set
        m_args_set[index] = true;
    }

    return ret;
}

bool cvk_kernel_argument_values::setup_descriptor_sets() {
    std::lock_guard<std::mutex> lock(m_lock);

    auto program = m_entry_point->program();
    auto dev = program->context()->device()->vulkan_device();

    // Do nothing if these argument values have already been used in an enqueue
    if (m_is_enqueued) {
        return true;
    }

    m_is_enqueued = true;

    // Allocate descriptor sets
    if (!m_entry_point->allocate_descriptor_sets(descriptor_sets())) {
        return false;
    }
    VkDescriptorSet* ds = descriptor_sets();

    // Make enough space to store all descriptor write structures
    size_t max_descriptor_writes =
        m_args.size() // upper bound that includes POD buffers
        + program->literal_sampler_descs().size() +
        1; // module constant data buffer
    std::vector<VkWriteDescriptorSet> descriptor_writes;
    std::vector<VkDescriptorBufferInfo> buffer_info;
    std::vector<VkDescriptorImageInfo> image_info;
    descriptor_writes.reserve(max_descriptor_writes);
    buffer_info.reserve(max_descriptor_writes);
    image_info.reserve(max_descriptor_writes);

    // Setup module-scope variables
    if (program->module_constant_data_buffer() != nullptr) {
        auto buffer = program->module_constant_data_buffer();
        auto info = program->module_constant_data_buffer_info();
        cvk_debug_fn(
            "constant data buffer %p, size = %zu @ set = %u, binding = %u",
            buffer->vulkan_buffer(), buffer->size(), info->set, info->binding);
        // Update descriptors
        VkDescriptorBufferInfo bufferInfo = {buffer->vulkan_buffer(),
                                             0, // offset
                                             VK_WHOLE_SIZE};
        buffer_info.push_back(bufferInfo);

        VkWriteDescriptorSet writeDescriptorSet = {
            VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
            nullptr,
            ds[info->set],
            info->binding,                     // dstBinding
            0,                                 // dstArrayElement
            1,                                 // descriptorCount
            VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // descriptorType
            nullptr,                           // pImageInfo
            &buffer_info.back(),
            nullptr, // pTexelBufferView
        };
        descriptor_writes.push_back(writeDescriptorSet);
    }

    // Setup descriptors for POD arguments
    if (m_entry_point->has_pod_buffer_arguments()) {
        // Create POD buffer
        if (!create_pod_buffer()) {
            return false;
        }

        // Update descriptors
        cvk_debug_fn("pod buffer %p, size = %zu @ set = %u, binding = %u",
                     m_pod_buffer->vulkan_buffer(), m_pod_buffer->size(),
                     m_pod_arg->descriptorSet, m_pod_arg->binding);
        VkDescriptorBufferInfo bufferInfo = {m_pod_buffer->vulkan_buffer(),
                                             0, // offset
                                             VK_WHOLE_SIZE};
        buffer_info.push_back(bufferInfo);

        VkWriteDescriptorSet writeDescriptorSet = {
            VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
            nullptr,
            ds[m_pod_arg->descriptorSet],
            m_pod_arg->binding,                   // dstBinding
            0,                                    // dstArrayElement
            1,                                    // descriptorCount
            m_entry_point->pod_descriptor_type(), // descriptorType
            nullptr,                              // pImageInfo
            &buffer_info.back(),
            nullptr, // pTexelBufferView
        };
        descriptor_writes.push_back(writeDescriptorSet);
    }

    // Setup other kernel argument descriptors
    for (cl_uint i = 0; i < m_args.size(); i++) {
        auto const& arg = m_args[i];

        switch (arg.kind) {

        case kernel_argument_kind::buffer:
        case kernel_argument_kind::buffer_ubo: {
            auto buffer = static_cast<cvk_buffer*>(get_arg_value(arg));
            if (buffer == nullptr) {
                cvk_debug_fn("ignoring NULL buffer argument");
                break;
            }
            auto vkbuf = buffer->vulkan_buffer();
            cvk_debug_fn(
                "buffer %p, offset = %zu, size = %zu @ set = %u, binding = %u",
                buffer->vulkan_buffer(), buffer->vulkan_buffer_offset(),
                buffer->size(), arg.descriptorSet, arg.binding);
            VkDescriptorBufferInfo bufferInfo = {
                vkbuf,
                buffer->vulkan_buffer_offset(), // offset
                buffer->size()};
            buffer_info.push_back(bufferInfo);

            auto descriptor_type = arg.kind == kernel_argument_kind::buffer
                                       ? VK_DESCRIPTOR_TYPE_STORAGE_BUFFER
                                       : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
            VkWriteDescriptorSet writeDescriptorSet = {
                VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
                nullptr,
                ds[arg.descriptorSet],
                arg.binding, // dstBinding
                0,           // dstArrayElement
                1,           // descriptorCount
                descriptor_type,
                nullptr, // pImageInfo
                &buffer_info.back(),
                nullptr, // pTexelBufferView
            };
            descriptor_writes.push_back(writeDescriptorSet);
            break;
        }
        case kernel_argument_kind::sampler: {
            auto clsampler = static_cast<cvk_sampler*>(get_arg_value(arg));
            auto sampler = clsampler->vulkan_sampler();

            cvk_debug_fn("sampler %p @ set = %u, binding = %u", sampler,
                         arg.descriptorSet, arg.binding);
            VkDescriptorImageInfo imageInfo = {
                sampler,
                VK_NULL_HANDLE,           // imageView
                VK_IMAGE_LAYOUT_UNDEFINED // imageLayout
            };
            image_info.push_back(imageInfo);

            VkWriteDescriptorSet writeDescriptorSet = {
                VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
                nullptr,
                ds[arg.descriptorSet],
                arg.binding, // dstBinding
                0,           // dstArrayElement
                1,           // descriptorCount
                VK_DESCRIPTOR_TYPE_SAMPLER,
                &image_info.back(), // pImageInfo
                nullptr,            // pBufferInfo
                nullptr,            // pTexelBufferView
            };
            descriptor_writes.push_back(writeDescriptorSet);
            break;
        }
        case kernel_argument_kind::ro_image:
        case kernel_argument_kind::wo_image: {
            auto image = static_cast<cvk_image*>(get_arg_value(arg));

            cvk_debug_fn("image view %p @ set = %u, binding = %u",
                         image->vulkan_image_view(), arg.descriptorSet,
                         arg.binding);
            VkDescriptorImageInfo imageInfo = {
                VK_NULL_HANDLE,
                image->vulkan_image_view(), // imageView
                VK_IMAGE_LAYOUT_GENERAL     // imageLayout
            };
            image_info.push_back(imageInfo);

            VkDescriptorType dtype = arg.kind == kernel_argument_kind::ro_image
                                         ? VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
                                         : VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;

            VkWriteDescriptorSet writeDescriptorSet = {
                VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
                nullptr,
                ds[arg.descriptorSet],
                arg.binding, // dstBinding
                0,           // dstArrayElement
                1,           // descriptorCount
                dtype,
                &image_info.back(), // pImageInfo
                nullptr,            // pBufferInfo
                nullptr,            // pTexelBufferView
            };
            descriptor_writes.push_back(writeDescriptorSet);
            break;
        }
        case kernel_argument_kind::pod: // skip POD arguments
        case kernel_argument_kind::pod_ubo:
        case kernel_argument_kind::pod_pushconstant:
            break;
        case kernel_argument_kind::local: // nothing to do?
            break;
        default:
            cvk_error_fn("unsupported argument type");
            return false;
        }
    }

    // Setup literal samplers
    for (size_t i = 0; i < program->literal_sampler_descs().size(); i++) {
        auto desc = program->literal_sampler_descs()[i];
        auto clsampler = icd_downcast(program->literal_samplers()[i]);
        auto sampler = clsampler->vulkan_sampler();

        VkDescriptorImageInfo imageInfo = {
            sampler,
            VK_NULL_HANDLE,           // imageView
            VK_IMAGE_LAYOUT_UNDEFINED // imageLayout
        };
        image_info.push_back(imageInfo);

        VkWriteDescriptorSet writeDescriptorSet = {
            VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
            nullptr,
            ds[desc.descriptorSet],
            desc.binding, // dstBinding
            0,            // dstArrayElement
            1,            // descriptorCount
            VK_DESCRIPTOR_TYPE_SAMPLER,
            &image_info.back(), // pImageInfo
            nullptr,            // pBufferInfo
            nullptr,            // pTexelBufferView
        };
        descriptor_writes.push_back(writeDescriptorSet);
    }

    // Write descriptors to device
    vkUpdateDescriptorSets(dev, static_cast<uint32_t>(descriptor_writes.size()),
                           descriptor_writes.data(), 0, nullptr);

    return true;
}
<|endoftext|>


<commit_before>#pragma once

#include "util/helpers.hpp"

#include <QDebug>
#include <QTime>

namespace chatterino {
namespace debug {

namespace detail {

static void _log(const std::string &message)
{
    qDebug().noquote() << QTime::currentTime().toString("hh:mm:ss.zzz") << message.c_str();
}

}  // namespace detail

template <typename... Args>
inline void Log(const std::string &formatString, Args &&... args)
{
    detail::_log(fS(formatString, std::forward<Args>(args)...));
}

}  // namespace debug
}  // namespace chatterino
<commit_msg>Simplify debug::Log. No need for a second function<commit_after>#pragma once

#include "util/helpers.hpp"

#include <QDebug>
#include <QTime>

namespace chatterino {
namespace debug {

template <typename... Args>
inline void Log(const std::string &formatString, Args &&... args)
{
    qDebug().noquote() << QTime::currentTime().toString("hh:mm:ss.zzz")
                       << fS(formatString, std::forward<Args>(args)...).c_str();
}

}  // namespace debug
}  // namespace chatterino
<|endoftext|>


<commit_before>#include <vector>
#include <string>
#include <fstream>
#include <iostream>
#include <cmath>
#include <memory>
#include <limits>

#include "scene.hpp"
#include "light.hpp"

using std::vector;
using std::auto_ptr;

/*
 * In the case of an empty constructor, Scene will generate a predefined
 * scene for rendering.
 */
Scene::Scene() : shapes(vector<Shape*>()),
                 lights(vector<LightSource*>()),
                 ambient(Color(0.25, 0.25, 0.25)),
                 camera(Camera())
{
    //floor
    shapes.push_back(new Plane(Point(0, -3, 0), Vector(0, 1, 0), Color(0, 1, 0), 1, 0.5, 0.5, 0.5));

    //back wall
    //shapes.push_back(new Plane(Point(0, 0, 20), Vector(0, 0, -1), Color(1, 1, 0), 1, 0.5, 0.5, 0.5));

    //left side wall
    //shapes.push_back(new Plane(Point(-3, 0, 0), Vector(1, 0, 0), Color(0, 1, 1), 1, 0.5, 0.5, 0.5));

    //right sphere (red)
    shapes.push_back(new Sphere(Point(3, -1, 5), 2,
                Color(1, 0, 0), 1, 0.9, 0.5, 0.5));

    //left sphere (blue)
    shapes.push_back(new Sphere(Point(-1, 2, 5), 1,
                Color(0, 0, 1), 1, 0.3, 0.5, 0.5));

    //light source 1
    //lights.push_back(new PointLight(Color(1, 1, 1), Point(0, .001, 2)));

    //light source 2
    lights.push_back(new PointLight(Color(1, 1, 1), Point(0, 5, 0)));
}

Scene::Scene(std::string fileName): shapes(vector<Shape*>()),
                                    lights(vector<LightSource*>()),
                                    ambient(Color(0.25, 0.25, 0.25)),
                                    camera(Camera()) {
    std::ifstream input_scene (fileName.c_str());
    // Read the file and add specified shapes.
    // We need to figure out what our syntax/grammar is first though.
}

Color Scene::raytrace(const Ray& camera_ray) const {
    const Shape *nearest_shape = NULL;
    float nearest_distance2 = std::numeric_limits<float>::max();
    Ray nearest_hit;
    for (vector<Shape*>::const_iterator it = shapes.begin(); it != shapes.end(); it++) {
        const Shape *shape = *it;
        auto_ptr<Ray> intersection(shape->getIntersection(camera_ray));
        if (intersection.get() == NULL) // Didn't hit this shape
            continue;
        float int_distance2 = Ray::makeRay(camera_ray.getOrigin(),
                intersection->getOrigin()).getDir().magnitude2();
        if (int_distance2 < nearest_distance2) {
            // Found a closer hit
            nearest_shape = shape;
            nearest_distance2 = int_distance2;
            nearest_hit = *intersection;
        }
    }
    if (nearest_shape == NULL) {
        // Didn't hit anything
        return Color(1, 0, 1); // Magenta
    } else {
        return shade(nearest_shape, nearest_hit);
    }
}

Color Scene::shade(const Shape *obj, Ray hit) const{
    /*
    if(hit.getDir().i==0 && hit.getDir().j==1 && hit.getDir().k==0){
        std::cout << hit.getOrigin().x << "\n";
        hit.getOrigin().x << ", " << hit.getOrigin().y << ", " << hit.getOrigin() << "\n";
        //return obj->getColor();

    }
    */
    for(vector<LightSource*>::const_iterator it = lights.begin(); it != lights.end(); it++) {
        LightSource *light = *it;
        Ray shadow = Ray::makeRay(hit.getOrigin(), light->getPoint());
        Color result = Color(ambient) * obj->getAmbientCoefficient();
        bool collision = false;
        // Detect collisions, for now do nothing if there is a collision
        for(vector<Shape*>::const_iterator sh = shapes.begin(); sh != shapes.end(); sh++) {
            Shape *shape = *sh;
            if (shape != obj){
                auto_ptr<Ray> hit(shape->getIntersection(shadow));
                if (hit.get() != NULL && hit->getOrigin() != shadow.getOrigin()) {
                    collision = true;
                    break;
                }
            }
        }
        // Calculate local illumination
        if(!collision) {
            // Normalize the direction vectors before calculations
            shadow.normalize();
            hit.normalize();

            float cos_theta = (shadow.getDir()).dotProduct(hit.getDir());
            /*
            if(!(hit.getDir().i==0 && hit.getDir().j==1 && hit.getDir().k==0)){
                //zprint:Vector(hit.getDir());
                std::cout<< hit.getDir().i << ",";
                std::cout<< hit.getDir().j << ",";
                std::cout<< hit.getDir().k << "\n";
            }
            */
            if(cos_theta < 0)
                cos_theta = 0;
            /*
            if(hit.getDir().i==0 && hit.getDir().j==1 && hit.getDir().k==0){
                std::cout<<cos_theta;
            }
            */
            Color diffuse = cos_theta * obj->getDiffuseCoefficient()
                * light->getColor();
            result = result + diffuse;
        }/*
        if(hit.getDir().i==0 && hit.getDir().j==1 && hit.getDir().k==0){

            std::cout<< result.red << ",";
            std::cout<< result.blue << ",";
            std::cout<< result.green << "\n";

        }*/
        result = result * obj->getColor();
        return result;
    }
}
Scene::~Scene() {
    for(vector<Shape*>::iterator it = shapes.begin(); it != shapes.end(); it++) {
        delete *it;
    }
    for(vector<LightSource*>::iterator it = lights.begin(); it != lights.end(); it++) {
        delete *it;
    }
}

Ray Scene::get_camera_ray(float x, float y) const {
    return camera.get_ray(x, -y);
}
class print{
    static void Vector(Vector v){
        std::cout<< v.i << ",";
        std::cout<< v.j << ",";
        std::cout<< v.k << "\n";
    }
};
<commit_msg>fixed shadows so that they only appear when the collision with the object happens before reaching the light<commit_after>#include <vector>
#include <string>
#include <fstream>
#include <iostream>
#include <cmath>
#include <memory>
#include <limits>

#include "scene.hpp"
#include "light.hpp"

using std::vector;
using std::auto_ptr;

/*
 * In the case of an empty constructor, Scene will generate a predefined
 * scene for rendering.
 */
Scene::Scene() : shapes(vector<Shape*>()),
                 lights(vector<LightSource*>()),
                 ambient(Color(0.25, 0.25, 0.25)),
                 camera(Camera())
{
    //floor
    shapes.push_back(new Plane(Point(0, -3, 0), Vector(0, 1, 0), Color(0, 1, 0), 1, 0.5, 0.5, 0.5));

    //back wall
    //shapes.push_back(new Plane(Point(0, 0, 20), Vector(0, 0, -1), Color(1, 1, 0), 1, 0.5, 0.5, 0.5));

    //left side wall
    //shapes.push_back(new Plane(Point(-3, 0, 0), Vector(1, 0, 0), Color(0, 1, 1), 1, 0.5, 0.5, 0.5));

    //right sphere (red)
    shapes.push_back(new Sphere(Point(3, -1, 5), 2,
                Color(1, 0, 0), 1, 0.9, 0.5, 0.5));

    //left sphere (blue)
    shapes.push_back(new Sphere(Point(-1, 2, 5), 1,
                Color(0, 0, 1), 1, 0.3, 0.5, 0.5));

    //light source 1
    //lights.push_back(new PointLight(Color(1, 1, 1), Point(0, .001, 2)));

    //light source 2
    lights.push_back(new PointLight(Color(1, 1, 1), Point(0, 5, 0)));
}

Scene::Scene(std::string fileName): shapes(vector<Shape*>()),
                                    lights(vector<LightSource*>()),
                                    ambient(Color(0.25, 0.25, 0.25)),
                                    camera(Camera()) {
    std::ifstream input_scene (fileName.c_str());
    // Read the file and add specified shapes.
    // We need to figure out what our syntax/grammar is first though.
}

Color Scene::raytrace(const Ray& camera_ray) const {
    const Shape *nearest_shape = NULL;
    float nearest_distance2 = std::numeric_limits<float>::max();
    Ray nearest_hit;
    for (vector<Shape*>::const_iterator it = shapes.begin(); it != shapes.end(); it++) {
        const Shape *shape = *it;
        auto_ptr<Ray> intersection(shape->getIntersection(camera_ray));
        if (intersection.get() == NULL) // Didn't hit this shape
            continue;
        float int_distance2 = Ray::makeRay(camera_ray.getOrigin(),
                intersection->getOrigin()).getDir().magnitude2();
        if (int_distance2 < nearest_distance2) {
            // Found a closer hit
            nearest_shape = shape;
            nearest_distance2 = int_distance2;
            nearest_hit = *intersection;
        }
    }
    if (nearest_shape == NULL) {
        // Didn't hit anything
        return Color(1, 0, 1); // Magenta
    } else {
        return shade(nearest_shape, nearest_hit);
    }
}

Color Scene::shade(const Shape *obj, Ray hit) const{
    /*
    if(hit.getDir().i==0 && hit.getDir().j==1 && hit.getDir().k==0){
        std::cout << hit.getOrigin().x << "\n";
        hit.getOrigin().x << ", " << hit.getOrigin().y << ", " << hit.getOrigin() << "\n";
        //return obj->getColor();

    }
    */
    for(vector<LightSource*>::const_iterator it = lights.begin(); it != lights.end(); it++) {
        LightSource *light = *it;
        Ray shadow = Ray::makeRay(hit.getOrigin(), light->getPoint());
        Color result = Color(ambient) * obj->getAmbientCoefficient();
        bool collision = false;
        // Detect collisions, for now do nothing if there is a collision
        for(vector<Shape*>::const_iterator sh = shapes.begin(); sh != shapes.end(); sh++) {
            Shape *shape = *sh;
            if (shape != obj){
                auto_ptr<Ray> hit(shape->getIntersection(shadow));
                if (hit.get() != NULL && hit->getOrigin() != shadow.getOrigin()) {
                    Vector toHit(hit->getOrigin().x-shadow.getOrigin().x,
                        hit->getOrigin().y-shadow.getOrigin().y,
                        hit->getOrigin().z-shadow.getOrigin().z);
                    if(fabs(toHit.i) <= fabs(shadow.getDir().i) &&
                        fabs(toHit.j) <= fabs(shadow.getDir().j) &&
                        fabs(toHit.k) <= fabs(shadow.getDir().k)){
                        collision = true;
                        break;
                    }
                }
            }
        }
        // Calculate local illumination
        if(!collision) {
            // Normalize the direction vectors before calculations
            shadow.normalize();
            hit.normalize();

            float cos_theta = (shadow.getDir()).dotProduct(hit.getDir());
            /*
            if(!(hit.getDir().i==0 && hit.getDir().j==1 && hit.getDir().k==0)){
                //zprint:Vector(hit.getDir());
                std::cout<< hit.getDir().i << ",";
                std::cout<< hit.getDir().j << ",";
                std::cout<< hit.getDir().k << "\n";
            }
            */
            if(cos_theta < 0)
                cos_theta = 0;
            /*
            if(hit.getDir().i==0 && hit.getDir().j==1 && hit.getDir().k==0){
                std::cout<<cos_theta;
            }
            */
            Color diffuse = cos_theta * obj->getDiffuseCoefficient()
                * light->getColor();
            result = result + diffuse;
        }/*
        if(hit.getDir().i==0 && hit.getDir().j==1 && hit.getDir().k==0){

            std::cout<< result.red << ",";
            std::cout<< result.blue << ",";
            std::cout<< result.green << "\n";

        }*/
        result = result * obj->getColor();
        return result;
    }
}
Scene::~Scene() {
    for(vector<Shape*>::iterator it = shapes.begin(); it != shapes.end(); it++) {
        delete *it;
    }
    for(vector<LightSource*>::iterator it = lights.begin(); it != lights.end(); it++) {
        delete *it;
    }
}

Ray Scene::get_camera_ray(float x, float y) const {
    return camera.get_ray(x, -y);
}
class print{
    static void Vector(Vector v){
        std::cout<< v.i << ",";
        std::cout<< v.j << ",";
        std::cout<< v.k << "\n";
    }
};
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://www.qtsoftware.com/contact.
**
**************************************************************************/

#include "debuggertooltip.h"

#include <QtCore/QPointer>
#include <QtCore/QtDebug>

#include <QtGui/QApplication>
#include <QtGui/QHBoxLayout>
#include <QtGui/QHeaderView>
#include <QtGui/QKeyEvent>
#include <QtGui/QLabel>
#include <QtGui/QTreeView>
#include <QtGui/QVBoxLayout>
#include <QtGui/QWidget>

namespace Debugger {
namespace Internal {

///////////////////////////////////////////////////////////////////////
//
// TooltipTreeView
//
///////////////////////////////////////////////////////////////////////

class ToolTipTreeView : public QTreeView
{
public:
    ToolTipTreeView(QWidget *parent = 0) : QTreeView(parent) {}

/*
    QSize sizeHint() const {
        qDebug() << viewport()->size()
            << viewport()->size().boundedTo(QSize(500, 300));
        return viewport()->size().boundedTo(QSize(100, 100));
    }
*/
};

///////////////////////////////////////////////////////////////////////
//
// TooltipWidget
//
///////////////////////////////////////////////////////////////////////

class ToolTipWidget : public QTreeView
{
    Q_OBJECT

public:
    ToolTipWidget(QWidget *parent);

    void done();
    void run(const QPoint &point, QAbstractItemModel *model,
        const QModelIndex &index, const QString &msg);
    bool eventFilter(QObject *ob, QEvent *ev);

    QSize sizeHint() const { return m_size; }

    int computeHeight(const QModelIndex &index)
    {
        int s = rowHeight(index);
        for (int i = 0; i < model()->rowCount(index); ++i)
            s += computeHeight(model()->index(i, 0, index));
        return s;
    }

    Q_SLOT void computeSize()
    {
        int columns = 0;
        for (int i = 0; i < 3; ++i) {
            resizeColumnToContents(i);
            columns += sizeHintForColumn(i);
        }
        int rows = computeHeight(QModelIndex());
        m_size = QSize(columns + 5, rows + 5);
        setMinimumSize(m_size);
        setMaximumSize(m_size);
    }
private:
    QSize m_size;
};

static QPointer<ToolTipWidget> theToolTipWidget;

ToolTipWidget::ToolTipWidget(QWidget *parent)
    : QTreeView(parent)
{
    setWindowFlags(Qt::ToolTip | Qt::WindowStaysOnTopHint);
    setFocusPolicy(Qt::NoFocus);

    header()->hide();

    setUniformRowHeights(true);
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

    connect(this, SIGNAL(collapsed(QModelIndex)), this, SLOT(computeSize()),
        Qt::QueuedConnection);
    connect(this, SIGNAL(expanded(QModelIndex)), this, SLOT(computeSize()),
        Qt::QueuedConnection);

    qApp->installEventFilter(this);
}

bool ToolTipWidget::eventFilter(QObject *ob, QEvent *ev)
{
    Q_UNUSED(ob);
    switch (ev->type()) {
    case QEvent::ShortcutOverride:
        if (static_cast<QKeyEvent *>(ev)->key() == Qt::Key_Escape)
            return true;
        break;
    case QEvent::KeyPress:
        if (static_cast<QKeyEvent *>(ev)->key() == Qt::Key_Escape) {
            return true;
        }
        break;
    case QEvent::KeyRelease:
        if (static_cast<QKeyEvent *>(ev)->key() == Qt::Key_Escape) {
            done();
            return true;
        }
        break;
    case QEvent::WindowDeactivate:
    case QEvent::FocusOut:
        done();
        break;
    default:
        break;
    }
    return false;
}

void ToolTipWidget::done()
{
    qApp->removeEventFilter(this);
    deleteLater();
}

void ToolTipWidget::run(const QPoint &point, QAbstractItemModel *model,
    const QModelIndex &index, const QString &msg)
{
    move(point);
    setModel(model);
    setRootIndex(index.parent());
    computeSize();
    setRootIsDecorated(model->hasChildren(index));
    // FIXME: use something more sensible
    QPalette pal = palette();
    QColor bg = pal.color(QPalette::Base);
    bg.setAlpha(20);
    pal.setColor(QPalette::Base, bg);
    setPalette(pal);
    //viewport()->setPalette(pal);
}

void showDebuggerToolTip(const QPoint &point, QAbstractItemModel *model,
        const QModelIndex &index, const QString &msg)
{
    if (model) {
        if (!theToolTipWidget)
            theToolTipWidget = new ToolTipWidget(0);
        theToolTipWidget->run(point, model, index, msg);
        theToolTipWidget->show();
    } else if (theToolTipWidget) {
        theToolTipWidget->done();
        theToolTipWidget = 0;
    }
}

void hideDebuggerToolTip(int delay)
{
    Q_UNUSED(delay)
    if (theToolTipWidget)
        theToolTipWidget->done();
}

} // namespace Internal
} // namespace Debugger

#include "debuggertooltip.moc"
<commit_msg>debugger: small copde cleanup in the debugger tooltip widget<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://www.qtsoftware.com/contact.
**
**************************************************************************/

#include "debuggertooltip.h"

#include <QtCore/QPointer>
#include <QtCore/QtDebug>

#include <QtGui/QApplication>
#include <QtGui/QHBoxLayout>
#include <QtGui/QHeaderView>
#include <QtGui/QKeyEvent>
#include <QtGui/QLabel>
#include <QtGui/QTreeView>
#include <QtGui/QVBoxLayout>
#include <QtGui/QWidget>

namespace Debugger {
namespace Internal {

class ToolTipWidget : public QTreeView
{
    Q_OBJECT

public:
    ToolTipWidget(QWidget *parent);

    bool eventFilter(QObject *ob, QEvent *ev);
    QSize sizeHint() const { return m_size; }

    void done();
    void run(const QPoint &point, QAbstractItemModel *model,
        const QModelIndex &index, const QString &msg);
    int computeHeight(const QModelIndex &index) const;
    Q_SLOT void computeSize();

private:
    QSize m_size;
};

static QPointer<ToolTipWidget> theToolTipWidget;

ToolTipWidget::ToolTipWidget(QWidget *parent)
    : QTreeView(parent)
{
    setWindowFlags(Qt::ToolTip | Qt::WindowStaysOnTopHint);
    setFocusPolicy(Qt::NoFocus);

    header()->hide();

    setUniformRowHeights(true);
    setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
    setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);

    connect(this, SIGNAL(collapsed(QModelIndex)), this, SLOT(computeSize()),
        Qt::QueuedConnection);
    connect(this, SIGNAL(expanded(QModelIndex)), this, SLOT(computeSize()),
        Qt::QueuedConnection);

    qApp->installEventFilter(this);
}

bool ToolTipWidget::eventFilter(QObject *ob, QEvent *ev)
{
    Q_UNUSED(ob);
    switch (ev->type()) {
    case QEvent::ShortcutOverride:
        if (static_cast<QKeyEvent *>(ev)->key() == Qt::Key_Escape)
            return true;
        break;
    case QEvent::KeyPress:
        if (static_cast<QKeyEvent *>(ev)->key() == Qt::Key_Escape) {
            return true;
        }
        break;
    case QEvent::KeyRelease:
        if (static_cast<QKeyEvent *>(ev)->key() == Qt::Key_Escape) {
            done();
            return true;
        }
        break;
    case QEvent::WindowDeactivate:
    case QEvent::FocusOut:
        done();
        break;
    default:
        break;
    }
    return false;
}

int ToolTipWidget::computeHeight(const QModelIndex &index) const
{
    int s = rowHeight(index);
    for (int i = 0; i < model()->rowCount(index); ++i)
        s += computeHeight(model()->index(i, 0, index));
    return s;
}

Q_SLOT void ToolTipWidget::computeSize()
{
    int columns = 0;
    for (int i = 0; i < 3; ++i) {
        resizeColumnToContents(i);
        columns += sizeHintForColumn(i);
    }
    int rows = computeHeight(QModelIndex());
    m_size = QSize(columns + 5, rows + 5);
    setMinimumSize(m_size);
    setMaximumSize(m_size);
}
void ToolTipWidget::done()
{
    qApp->removeEventFilter(this);
    deleteLater();
}

void ToolTipWidget::run(const QPoint &point, QAbstractItemModel *model,
    const QModelIndex &index, const QString &msg)
{
    move(point);
    setModel(model);
    setRootIndex(index.parent());
    computeSize();
    setRootIsDecorated(model->hasChildren(index));
    // FIXME: use something more sensible
    QPalette pal = palette();
    QColor bg = pal.color(QPalette::Base);
    bg.setAlpha(20);
    pal.setColor(QPalette::Base, bg);
    setPalette(pal);
    //viewport()->setPalette(pal);
}

void showDebuggerToolTip(const QPoint &point, QAbstractItemModel *model,
        const QModelIndex &index, const QString &msg)
{
    if (model) {
        if (!theToolTipWidget)
            theToolTipWidget = new ToolTipWidget(0);
        theToolTipWidget->run(point, model, index, msg);
        theToolTipWidget->show();
    } else if (theToolTipWidget) {
        theToolTipWidget->done();
        theToolTipWidget = 0;
    }
}

void hideDebuggerToolTip(int delay)
{
    Q_UNUSED(delay)
    if (theToolTipWidget)
        theToolTipWidget->done();
}

} // namespace Internal
} // namespace Debugger

#include "debuggertooltip.moc"
<|endoftext|>


<commit_before>/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include "paddle/fluid/inference/tensorrt/engine.h"

#include <NvInfer.h>
#include <cuda.h>
#include <glog/logging.h>
#include <string>
#include "paddle/fluid/inference/analysis/helper.h"
#include "paddle/fluid/inference/tensorrt/helper.h"
#include "paddle/fluid/platform/enforce.h"

namespace paddle {
namespace inference {
namespace tensorrt {

int TensorRTEngine::runtime_batch_ = 1;

void TensorRTEngine::Build(const DescType &paddle_model) {
  PADDLE_ENFORCE(false, "not implemented");
}

void TensorRTEngine::Execute(int batch_size, std::vector<void *> *buffers,
                             cudaStream_t stream) {
  freshDeviceId();
  batch_size_ = batch_size;
  infer_context_->enqueue(batch_size, buffers->data(), stream, nullptr);
  cudaStreamSynchronize(stream);
  SetRuntimeBatch(batch_size);
}

void TensorRTEngine::FreezeNetwork() {
  freshDeviceId();
  VLOG(3) << "TRT to freeze network";
  PADDLE_ENFORCE(infer_builder_ != nullptr,
                 "Call InitNetwork first to initialize network.");
  PADDLE_ENFORCE(infer_network_ != nullptr,
                 "Call InitNetwork first to initialize network.");
  // build engine.
  infer_builder_->setMaxBatchSize(max_batch_);
  infer_builder_->setMaxWorkspaceSize(max_workspace_);
  bool enable_fp16 = (precision_ == AnalysisConfig::Precision::kHalf);
  if (enable_fp16) {
    bool support_fp16 = infer_builder_->platformHasFastFp16();
    infer_builder_->setFp16Mode(support_fp16);
    if (!support_fp16) {
      LOG(INFO) << "You specify FP16 mode, but the hardware do not support "
                   "FP16 speed up, use FP32 instead.";
    }
  }
  bool enable_int8 = (precision_ == AnalysisConfig::Precision::kInt8);

  if (enable_int8) {
    infer_builder_->setInt8Mode(true);
    if (calibrator_) {
      infer_builder_->setInt8Calibrator(calibrator_);
    } else {
      infer_builder_->setInt8Calibrator(nullptr);

#if IS_TRT_VERSION_GE(5000)
      infer_builder_->setStrictTypeConstraints(true);
      for (auto &quant_range : quant_dynamic_range_) {
        auto tensor = quant_range.first;
        float range = quant_range.second;
        tensor->setDynamicRange(-range, range);
      }

      std::unordered_set<nvinfer1::ITensor *> all_t;
      for (int i = 0; i < infer_network_->getNbLayers(); i++) {
        auto layer = infer_network_->getLayer(i);
        for (int j = 0; j < layer->getNbOutputs(); j++) {
          all_t.insert(layer->getOutput(j));
        }
      }
      for (int i = 0; i < infer_network_->getNbInputs(); i++) {
        all_t.insert(infer_network_->getInput(i));
      }

      for (auto &t : all_t) {
        if (!quant_dynamic_range_.count(t)) {
          LOG(WARNING)
              << "We are in trt int8 mode(not calibration), scale not setted"
              << " for tensor " << t->getName()
              << ", this might be ok when trt does not need this range";
        }
      }
#endif
    }
  }

  infer_engine_.reset(infer_builder_->buildCudaEngine(*infer_network_));
  PADDLE_ENFORCE(infer_engine_ != nullptr, "build cuda engine failed!");

  infer_context_.reset(infer_engine_->createExecutionContext());
}

nvinfer1::ITensor *TensorRTEngine::DeclareInput(const std::string &name,
                                                nvinfer1::DataType dtype,
                                                const nvinfer1::Dims &dims) {
  PADDLE_ENFORCE_EQ(0, buffer_sizes_.count(name), "duplicate input name %s",
                    name);

  PADDLE_ENFORCE(infer_network_ != nullptr, "should initnetwork first");
  auto *input = infer_network_->addInput(name.c_str(), dtype, dims);
  PADDLE_ENFORCE(input, "infer network add input %s failed", name);
  buffer_sizes_[name] = kDataTypeSize[static_cast<int>(dtype)] *
                        analysis::AccuDims(dims.d, dims.nbDims) * max_batch_;
  PADDLE_ENFORCE(input->isNetworkInput());
  TensorRTEngine::SetITensor(name, input);
  return input;
}

void TensorRTEngine::DeclareOutput(const nvinfer1::ILayer *layer, int offset,
                                   const std::string &name) {
  PADDLE_ENFORCE_EQ(0, buffer_sizes_.count(name), "duplicate output name %s",
                    name);

  auto *output = layer->getOutput(offset);
  SetITensor(name, output);
  PADDLE_ENFORCE(output != nullptr);
  output->setName(name.c_str());
  PADDLE_ENFORCE(!output->isNetworkInput());
  infer_network_->markOutput(*output);
  PADDLE_ENFORCE(output->isNetworkOutput());
  // output buffers' size can only be decided latter, set zero here to mark this
  // and will reset latter.
  buffer_sizes_[name] = 0;
}

bool TensorRTEngine::HasDeclared(const std::string &name) {
  return buffer_sizes_.count(name) > 0;
}

void TensorRTEngine::DeclareOutput(const std::string &name) {
  PADDLE_ENFORCE_EQ(0, buffer_sizes_.count(name), "duplicate output name %s",
                    name);

  auto *output = TensorRTEngine::GetITensor(name);
  PADDLE_ENFORCE(output != nullptr);
  output->setName(name.c_str());
  PADDLE_ENFORCE(!output->isNetworkInput());
  infer_network_->markOutput(*output);
  // output buffers' size can only be decided latter, set zero here to mark this
  // and will reset latter.
  buffer_sizes_[name] = 0;
}

void TensorRTEngine::SetITensor(const std::string &name,
                                nvinfer1::ITensor *tensor) {
  PADDLE_ENFORCE(tensor != nullptr);
  PADDLE_ENFORCE_EQ(0, itensor_map_.count(name), "duplicate ITensor name %s",
                    name);
  itensor_map_[name] = tensor;
}

nvinfer1::ITensor *TensorRTEngine::GetITensor(const std::string &name) {
  PADDLE_ENFORCE(itensor_map_.count(name), "no ITensor %s", name);
  return itensor_map_[name];
}

void TensorRTEngine::SetRuntimeBatch(size_t batch_size) {
  runtime_batch_ = batch_size;
}

float *TensorRTEngine::GetWeightCPUData(const std::string &name,
                                        framework::Tensor *weight_tensor,
                                        bool enable_int8,
                                        const std::vector<float> &scale) {
  auto w_dims = weight_tensor->dims();
  platform::CPUPlace cpu_place;
  PADDLE_ENFORCE(!weight_map.count(name),
                 "During TRT Op converter: We set weight %s with the same name "
                 "twice into the weight_map",
                 name);
  weight_map[name].reset(new framework::Tensor());
  weight_map[name]->Resize(weight_tensor->dims());
  TensorCopySync(*weight_tensor, cpu_place, weight_map[name].get());
  float *weight_data = weight_map[name]->mutable_data<float>(cpu_place);

  if (enable_int8) {
    // when the op is fc, scale's size should be 1
    // when the op is conv, the scale's size should be w_dims[0]
    bool valid_scale_size =
        (scale.size() == 1 || scale.size() == static_cast<size_t>(w_dims[0]));
    PADDLE_ENFORCE(valid_scale_size, "TRT int8 quant: invalid scale size");
    for (int i = 0; i < weight_tensor->numel(); i++) {
      bool is_valid_int8 =
          ((weight_data[i] >= -128) && (weight_data[i] <= 127));
      PADDLE_ENFORCE(is_valid_int8,
                     "We are in anakin subgraph int8 mode, the weight of conv "
                     "should be in range [-128, 127]");
      if (scale.size() == 1) {
        weight_data[i] *= (scale[0] / 127);
      } else {
        PADDLE_ENFORCE(w_dims.size() == 4,
                       "TRT int8 quant : We only use the channel quant for "
                       "conv op, so the weight dims should be 4.");
        int inner_size = w_dims[1] * w_dims[2] * w_dims[3];
        weight_data[i] *= (scale[i / inner_size] / 127);
      }
    }
  }
  return weight_data;
}

int TensorRTEngine::GetRuntimeBatch() { return runtime_batch_; }

nvinfer1::IPluginLayer *TensorRTEngine::AddPlugin(
    nvinfer1::ITensor *const *inputs, int num_inputs,
    plugin::PluginTensorRT *plugin) {
  owned_plugin_.emplace_back(plugin);
  return infer_network_.get()->addPluginExt(inputs, num_inputs, *plugin);
}

void TensorRTEngine::freshDeviceId() {
  int count;
  cudaGetDeviceCount(&count);
  PADDLE_ENFORCE_LT(device_id_, count);
  cudaSetDevice(device_id_);
}

}  // namespace tensorrt
}  // namespace inference
}  // namespace paddle
<commit_msg>Fix the CE error which caused by paddle-trt version (#18941)<commit_after>/* Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

#include "paddle/fluid/inference/tensorrt/engine.h"

#include <NvInfer.h>
#include <cuda.h>
#include <glog/logging.h>
#include <string>
#include "paddle/fluid/inference/analysis/helper.h"
#include "paddle/fluid/inference/tensorrt/helper.h"
#include "paddle/fluid/platform/enforce.h"

namespace paddle {
namespace inference {
namespace tensorrt {

int TensorRTEngine::runtime_batch_ = 1;

void TensorRTEngine::Build(const DescType &paddle_model) {
  PADDLE_ENFORCE(false, "not implemented");
}

void TensorRTEngine::Execute(int batch_size, std::vector<void *> *buffers,
                             cudaStream_t stream) {
  freshDeviceId();
  batch_size_ = batch_size;
  infer_context_->enqueue(batch_size, buffers->data(), stream, nullptr);
  cudaStreamSynchronize(stream);
  SetRuntimeBatch(batch_size);
}

void TensorRTEngine::FreezeNetwork() {
  freshDeviceId();
  VLOG(3) << "TRT to freeze network";
  PADDLE_ENFORCE(infer_builder_ != nullptr,
                 "Call InitNetwork first to initialize network.");
  PADDLE_ENFORCE(infer_network_ != nullptr,
                 "Call InitNetwork first to initialize network.");
  // build engine.
  infer_builder_->setMaxBatchSize(max_batch_);
  infer_builder_->setMaxWorkspaceSize(max_workspace_);
#if IS_TRT_VERSION_GE(5000)
  bool enable_fp16 = (precision_ == AnalysisConfig::Precision::kHalf);
  if (enable_fp16) {
    bool support_fp16 = infer_builder_->platformHasFastFp16();
    infer_builder_->setFp16Mode(support_fp16);
    if (!support_fp16) {
      LOG(INFO) << "You specify FP16 mode, but the hardware do not support "
                   "FP16 speed up, use FP32 instead.";
    }
  }
#else
  LOG(INFO) << "Using FP16 in Paddle-trt must ensure that the version of TRT "
               "is at least 5."
               "So, use FP32 to run.";
#endif
  bool enable_int8 = (precision_ == AnalysisConfig::Precision::kInt8);

  if (enable_int8) {
    infer_builder_->setInt8Mode(true);
    if (calibrator_) {
      infer_builder_->setInt8Calibrator(calibrator_);
    } else {
      infer_builder_->setInt8Calibrator(nullptr);

#if IS_TRT_VERSION_GE(5000)
      infer_builder_->setStrictTypeConstraints(true);
      for (auto &quant_range : quant_dynamic_range_) {
        auto tensor = quant_range.first;
        float range = quant_range.second;
        tensor->setDynamicRange(-range, range);
      }

      std::unordered_set<nvinfer1::ITensor *> all_t;
      for (int i = 0; i < infer_network_->getNbLayers(); i++) {
        auto layer = infer_network_->getLayer(i);
        for (int j = 0; j < layer->getNbOutputs(); j++) {
          all_t.insert(layer->getOutput(j));
        }
      }
      for (int i = 0; i < infer_network_->getNbInputs(); i++) {
        all_t.insert(infer_network_->getInput(i));
      }

      for (auto &t : all_t) {
        if (!quant_dynamic_range_.count(t)) {
          LOG(WARNING)
              << "We are in trt int8 mode(not calibration), scale not setted"
              << " for tensor " << t->getName()
              << ", this might be ok when trt does not need this range";
        }
      }
#endif
    }
  }

  infer_engine_.reset(infer_builder_->buildCudaEngine(*infer_network_));
  PADDLE_ENFORCE(infer_engine_ != nullptr, "build cuda engine failed!");

  infer_context_.reset(infer_engine_->createExecutionContext());
}

nvinfer1::ITensor *TensorRTEngine::DeclareInput(const std::string &name,
                                                nvinfer1::DataType dtype,
                                                const nvinfer1::Dims &dims) {
  PADDLE_ENFORCE_EQ(0, buffer_sizes_.count(name), "duplicate input name %s",
                    name);

  PADDLE_ENFORCE(infer_network_ != nullptr, "should initnetwork first");
  auto *input = infer_network_->addInput(name.c_str(), dtype, dims);
  PADDLE_ENFORCE(input, "infer network add input %s failed", name);
  buffer_sizes_[name] = kDataTypeSize[static_cast<int>(dtype)] *
                        analysis::AccuDims(dims.d, dims.nbDims) * max_batch_;
  PADDLE_ENFORCE(input->isNetworkInput());
  TensorRTEngine::SetITensor(name, input);
  return input;
}

void TensorRTEngine::DeclareOutput(const nvinfer1::ILayer *layer, int offset,
                                   const std::string &name) {
  PADDLE_ENFORCE_EQ(0, buffer_sizes_.count(name), "duplicate output name %s",
                    name);

  auto *output = layer->getOutput(offset);
  SetITensor(name, output);
  PADDLE_ENFORCE(output != nullptr);
  output->setName(name.c_str());
  PADDLE_ENFORCE(!output->isNetworkInput());
  infer_network_->markOutput(*output);
  PADDLE_ENFORCE(output->isNetworkOutput());
  // output buffers' size can only be decided latter, set zero here to mark this
  // and will reset latter.
  buffer_sizes_[name] = 0;
}

bool TensorRTEngine::HasDeclared(const std::string &name) {
  return buffer_sizes_.count(name) > 0;
}

void TensorRTEngine::DeclareOutput(const std::string &name) {
  PADDLE_ENFORCE_EQ(0, buffer_sizes_.count(name), "duplicate output name %s",
                    name);

  auto *output = TensorRTEngine::GetITensor(name);
  PADDLE_ENFORCE(output != nullptr);
  output->setName(name.c_str());
  PADDLE_ENFORCE(!output->isNetworkInput());
  infer_network_->markOutput(*output);
  // output buffers' size can only be decided latter, set zero here to mark this
  // and will reset latter.
  buffer_sizes_[name] = 0;
}

void TensorRTEngine::SetITensor(const std::string &name,
                                nvinfer1::ITensor *tensor) {
  PADDLE_ENFORCE(tensor != nullptr);
  PADDLE_ENFORCE_EQ(0, itensor_map_.count(name), "duplicate ITensor name %s",
                    name);
  itensor_map_[name] = tensor;
}

nvinfer1::ITensor *TensorRTEngine::GetITensor(const std::string &name) {
  PADDLE_ENFORCE(itensor_map_.count(name), "no ITensor %s", name);
  return itensor_map_[name];
}

void TensorRTEngine::SetRuntimeBatch(size_t batch_size) {
  runtime_batch_ = batch_size;
}

float *TensorRTEngine::GetWeightCPUData(const std::string &name,
                                        framework::Tensor *weight_tensor,
                                        bool enable_int8,
                                        const std::vector<float> &scale) {
  auto w_dims = weight_tensor->dims();
  platform::CPUPlace cpu_place;
  PADDLE_ENFORCE(!weight_map.count(name),
                 "During TRT Op converter: We set weight %s with the same name "
                 "twice into the weight_map",
                 name);
  weight_map[name].reset(new framework::Tensor());
  weight_map[name]->Resize(weight_tensor->dims());
  TensorCopySync(*weight_tensor, cpu_place, weight_map[name].get());
  float *weight_data = weight_map[name]->mutable_data<float>(cpu_place);

  if (enable_int8) {
    // when the op is fc, scale's size should be 1
    // when the op is conv, the scale's size should be w_dims[0]
    bool valid_scale_size =
        (scale.size() == 1 || scale.size() == static_cast<size_t>(w_dims[0]));
    PADDLE_ENFORCE(valid_scale_size, "TRT int8 quant: invalid scale size");
    for (int i = 0; i < weight_tensor->numel(); i++) {
      bool is_valid_int8 =
          ((weight_data[i] >= -128) && (weight_data[i] <= 127));
      PADDLE_ENFORCE(is_valid_int8,
                     "We are in anakin subgraph int8 mode, the weight of conv "
                     "should be in range [-128, 127]");
      if (scale.size() == 1) {
        weight_data[i] *= (scale[0] / 127);
      } else {
        PADDLE_ENFORCE(w_dims.size() == 4,
                       "TRT int8 quant : We only use the channel quant for "
                       "conv op, so the weight dims should be 4.");
        int inner_size = w_dims[1] * w_dims[2] * w_dims[3];
        weight_data[i] *= (scale[i / inner_size] / 127);
      }
    }
  }
  return weight_data;
}

int TensorRTEngine::GetRuntimeBatch() { return runtime_batch_; }

nvinfer1::IPluginLayer *TensorRTEngine::AddPlugin(
    nvinfer1::ITensor *const *inputs, int num_inputs,
    plugin::PluginTensorRT *plugin) {
  owned_plugin_.emplace_back(plugin);
  return infer_network_.get()->addPluginExt(inputs, num_inputs, *plugin);
}

void TensorRTEngine::freshDeviceId() {
  int count;
  cudaGetDeviceCount(&count);
  PADDLE_ENFORCE_LT(device_id_, count);
  cudaSetDevice(device_id_);
}

}  // namespace tensorrt
}  // namespace inference
}  // namespace paddle
<|endoftext|>


<commit_before>#include "TrackingWorker.hpp"

#include <boost/chrono/duration.hpp>
#include <ros/console.h>
#include <opencv2/core/core.hpp>
#include <map>

#include "../../matlab/profiling.hpp"

TrackingWorker::TrackingWorker(IPositionReceiver *receiver) : errorGraph(100, "Difference")
{
	assert(receiver != 0);

	this->receiver = receiver;
	stop = false;

	std::map<int, cv::Scalar> colors;
	colors[0] = cv::Scalar(0, 255, 0);
	colors[1] = cv::Scalar(0, 255, 255);
	colors[2] = cv::Scalar(255, 0, 255);
	errorGraph.setColors(colors);

	thread = new boost::thread(boost::bind(&TrackingWorker::run, this));
}

TrackingWorker::~TrackingWorker()
{
	stop = true;
	thread->join();
}

void TrackingWorker::run()
{
	ROS_INFO("Started tracking thread");

	bool receivedFirstPosition = false;
	int emptyCount = 0;

	while (!stop) {
		std::vector<CameraData> data = dequeue();

		if (data.size() > 0) {
			emptyCount = 0;

			if (!receivedFirstPosition) {
				receivedFirstPosition = true;
				ROS_INFO("Found quadcopter %d", data[0].quadcopterId);
			}

			// ROS_DEBUG("Got info from camera %d: [%.2f, %.2f, %.2f]", data[0].camNo, data[0].cameraVector.getV1(), data[0].cameraVector.getV2(), data[0].cameraVector.getV3());

			Vector position = tracker.updatePosition(data);

			for (size_t i = 0; i < data.size(); i++) {
				errorGraph.nextPoint(tracker.getDistance(), data[i].camNo);
			}

			if (position.isValid()) {
				// Invert x axis for controller
				position.setV1(-position.getV1());

				std::vector<Vector> positions;
				std::vector<int> ids;
				std::vector<int> updates;
				positions.push_back(position);
				ids.push_back(data[0].quadcopterId);
				updates.push_back(1);

				receiver->updatePositions(positions, ids, updates);
			}
		} else if (receivedFirstPosition) {
			emptyCount++;

			if (emptyCount == 50) {
				ROS_WARN("Position update buffer is empty!");
				emptyCount = 0;
			}

			boost::mutex::scoped_lock lock(queueMutex);
			queueEmpty.wait(lock);
		}
	}

	ROS_INFO("Stopped tracking thread");
}

void TrackingWorker::updatePosition(Vector cameraVector, int camNo, int quadcopterId, long int time)
{
	CameraData data;
	data.cameraVector = cameraVector;
	data.camNo = camNo;
	data.quadcopterId = quadcopterId;
	data.valid = true;
	data.time = time;

	updatePosition(data);
}

void TrackingWorker::updatePosition(CameraData data)
{
	enqueue(data);
}

void TrackingWorker::enqueue(CameraData data)
{
	boost::mutex::scoped_lock lock(queueMutex);

	queue.enqueue(data);

	queueEmpty.notify_all();
}

std::vector<CameraData> TrackingWorker::dequeue()
{
	boost::mutex::scoped_lock lock(queueMutex);

	if (!dataAvailable()) {
		queueEmpty.timed_wait(lock, boost::get_system_time() + boost::posix_time::milliseconds(100));
	}

	if (dataAvailable()) {
		return queue.dequeue();
	} else {
		return std::vector<CameraData>();
	}
}

bool TrackingWorker::dataAvailable()
{
	return queue.dataAvailable();
}

bool TrackingWorker::calibrate(ChessboardData *chessboard, int camNo)
{
	return tracker.calibrate(chessboard, camNo);
}

Vector TrackingWorker::getCameraPosition(int camNo)
{
	return tracker.getPosition(camNo);
}

cv::Mat TrackingWorker::getIntrinsicsMatrix(int camNo)
{
	return tracker.getIntrinsicsMatrix(camNo);
}

cv::Mat TrackingWorker::getDistortionCoefficients(int camNo)
{
	return tracker.getDistortionCoefficients(camNo);
}

void TrackingWorker::updateTrackingArea()
{
	receiver->setTrackingArea(tracker.getTrackingArea());
}
<commit_msg>Uncommented warnings<commit_after>#include "TrackingWorker.hpp"

#include <boost/chrono/duration.hpp>
#include <ros/console.h>
#include <opencv2/core/core.hpp>
#include <map>

#include "../../matlab/profiling.hpp"

TrackingWorker::TrackingWorker(IPositionReceiver *receiver) : errorGraph(100, "Difference")
{
	assert(receiver != 0);

	this->receiver = receiver;
	stop = false;

	std::map<int, cv::Scalar> colors;
	colors[0] = cv::Scalar(0, 255, 0);
	colors[1] = cv::Scalar(0, 255, 255);
	colors[2] = cv::Scalar(255, 0, 255);
	errorGraph.setColors(colors);

	thread = new boost::thread(boost::bind(&TrackingWorker::run, this));
}

TrackingWorker::~TrackingWorker()
{
	stop = true;
	thread->join();
}

void TrackingWorker::run()
{
	ROS_INFO("Started tracking thread");

	bool receivedFirstPosition = false;
	int emptyCount = 0;

	while (!stop) {
		std::vector<CameraData> data = dequeue();

		if (data.size() > 0) {
			emptyCount = 0;

			if (!receivedFirstPosition) {
				receivedFirstPosition = true;
				ROS_INFO("Found quadcopter %d", data[0].quadcopterId);
			}

			// ROS_DEBUG("Got info from camera %d: [%.2f, %.2f, %.2f]", data[0].camNo, data[0].cameraVector.getV1(), data[0].cameraVector.getV2(), data[0].cameraVector.getV3());

			Vector position = tracker.updatePosition(data);

			for (size_t i = 0; i < data.size(); i++) {
				errorGraph.nextPoint(tracker.getDistance(), data[i].camNo);
			}

			if (position.isValid()) {
				// Invert x axis for controller
				position.setV1(-position.getV1());

				std::vector<Vector> positions;
				std::vector<int> ids;
				std::vector<int> updates;
				positions.push_back(position);
				ids.push_back(data[0].quadcopterId);
				updates.push_back(1);

				receiver->updatePositions(positions, ids, updates);
			}
		} else if (receivedFirstPosition) {
			emptyCount++;

			if (emptyCount == 50) {
				// TODO uncomment
				// ROS_WARN("Position update buffer is empty!");
				emptyCount = 0;
			}

			boost::mutex::scoped_lock lock(queueMutex);
			queueEmpty.wait(lock);
		}
	}

	ROS_INFO("Stopped tracking thread");
}

void TrackingWorker::updatePosition(Vector cameraVector, int camNo, int quadcopterId, long int time)
{
	CameraData data;
	data.cameraVector = cameraVector;
	data.camNo = camNo;
	data.quadcopterId = quadcopterId;
	data.valid = true;
	data.time = time;

	updatePosition(data);
}

void TrackingWorker::updatePosition(CameraData data)
{
	enqueue(data);
}

void TrackingWorker::enqueue(CameraData data)
{
	boost::mutex::scoped_lock lock(queueMutex);

	queue.enqueue(data);

	queueEmpty.notify_all();
}

std::vector<CameraData> TrackingWorker::dequeue()
{
	boost::mutex::scoped_lock lock(queueMutex);

	if (!dataAvailable()) {
		queueEmpty.timed_wait(lock, boost::get_system_time() + boost::posix_time::milliseconds(100));
	}

	if (dataAvailable()) {
		return queue.dequeue();
	} else {
		return std::vector<CameraData>();
	}
}

bool TrackingWorker::dataAvailable()
{
	return queue.dataAvailable();
}

bool TrackingWorker::calibrate(ChessboardData *chessboard, int camNo)
{
	return tracker.calibrate(chessboard, camNo);
}

Vector TrackingWorker::getCameraPosition(int camNo)
{
	return tracker.getPosition(camNo);
}

cv::Mat TrackingWorker::getIntrinsicsMatrix(int camNo)
{
	return tracker.getIntrinsicsMatrix(camNo);
}

cv::Mat TrackingWorker::getDistortionCoefficients(int camNo)
{
	return tracker.getDistortionCoefficients(camNo);
}

void TrackingWorker::updateTrackingArea()
{
	receiver->setTrackingArea(tracker.getTrackingArea());
}
<|endoftext|>


<commit_before>#pragma once

#include "base/assert.hpp"
#include "base/string_utils.hpp"

#include <algorithm>
#include <cmath>
#include <cstddef>
#include <sstream>
#include <string>
#include <utility>

#include <boost/optional.hpp>

namespace search
{
template <typename Token>
struct TokenWeightPair
{
  TokenWeightPair() = default;

  template <typename T>
  TokenWeightPair(T && token, double weight) : m_token(std::forward<T>(token)), m_weight(weight)
  {
  }

  bool operator<(TokenWeightPair const & rhs) const
  {
    if (m_token != rhs.m_token)
      return m_token < rhs.m_token;
    return m_weight < rhs.m_weight;
  }

  void Swap(TokenWeightPair & rhs)
  {
    m_token.swap(rhs.m_token);
    std::swap(m_weight, rhs.m_weight);
  }

  // Returns squared weight of the token-weight pair.
  double Sqr() const { return m_weight * m_weight; }

  Token m_token;
  double m_weight = 0;
};

template <typename Token>
std::string DebugPrint(TokenWeightPair<Token> const & tw)
{
  std::ostringstream os;
  os << "TokenWeightPair [ " << DebugPrint(tw.m_token) << ", " << tw.m_weight << " ]";
  return os.str();
}

namespace impl
{
// Accumulates weights of equal tokens in |tws|. Result is sorted by tokens.
template <typename Token>
void SortAndMerge(std::vector<TokenWeightPair<Token>> & tws)
{
  std::sort(tws.begin(), tws.end());
  size_t n = 0;
  for (size_t i = 0; i < tws.size(); ++i)
  {
    ASSERT_LESS_OR_EQUAL(n, i, ());
    if (n == 0 || tws[n - 1].m_token != tws[i].m_token)
    {
      tws[n].Swap(tws[i]);
      ++n;
    }
    else
    {
      tws[n - 1].m_weight += tws[i].m_weight;
    }
  }

  ASSERT_LESS_OR_EQUAL(n, tws.size(), ());
  tws.erase(tws.begin() + n, tws.end());
}

// Computes squared L2 norm of vector of tokens.
template <typename Token>
double SqrL2(std::vector<TokenWeightPair<Token>> const & tws)
{
  double sum = 0;
  for (auto const & tw : tws)
    sum += tw.Sqr();
  return sum;
}

// Computes squared L2 norm of vector of tokens + prefix token.
template <typename Token>
double SqrL2(std::vector<TokenWeightPair<Token>> const & tws,
             boost::optional<TokenWeightPair<Token>> const & prefix)
{
  double result = SqrL2(tws);
  return result + (prefix ? prefix->Sqr() : 0);
}
}  // namespace impl

// This class represents a document in a vector space of tokens.
template <typename Token>
class DocVec
{
public:
  using TokenWeightPair = TokenWeightPair<Token>;
  using TokenWeightPairs = std::vector<TokenWeightPair>;

  class Builder
  {
  public:
    template <typename T>
    void Add(T && token, double weight)
    {
      m_tws.emplace_back(std::forward<T>(token), weight);
    }

  private:
    friend class DocVec;

    std::vector<TokenWeightPair> m_tws;
  };

  DocVec() = default;
  explicit DocVec(Builder && builder) : m_tws(std::move(builder.m_tws)) { Init(); }
  explicit DocVec(Builder const & builder) : m_tws(builder.m_tws) { Init(); }

  TokenWeightPairs const & GetTokenWeightPairs() const { return m_tws; }

  bool Empty() const { return m_tws.empty(); }

private:
  template <typename T>
  friend std::string DebugPrint(DocVec<T> const & dv)
  {
    return "DocVec " + DebugPrint(dv.m_tws);
  }

  void Init() { impl::SortAndMerge(m_tws); }

  TokenWeightPairs m_tws;
};

// This class represents a search query in a vector space of tokens.
template <typename Token>
class QueryVec
{
public:
  using TokenWeightPair = TokenWeightPair<Token>;

  class Builder
  {
  public:
    template <typename T>
    void AddFull(T && token, double weight)
    {
      m_tws.emplace_back(std::forward<T>(token), weight);
    }

    template <typename T>
    void SetPrefix(T && token, double weight)
    {
      m_prefix = TokenWeightPair(std::forward<T>(token), weight);
    }

  private:
    friend class QueryVec;

    std::vector<TokenWeightPair> m_tws;
    boost::optional<TokenWeightPair> m_prefix;
  };

  QueryVec() = default;

  explicit QueryVec(Builder && builder)
    : m_tws(std::move(builder.m_tws)), m_prefix(std::move(builder.m_prefix))
  {
    Init();
  }

  explicit QueryVec(Builder const & builder) : m_tws(builder.m_tws), m_prefix(builder.m_prefix)
  {
    Init();
  }

  // Computes cosine distance between |*this| and |rhs|.
  double Similarity(DocVec<Token> const & rhs) const
  {
    size_t kInvalidIndex = std::numeric_limits<size_t>::max();

    if (Empty() && rhs.Empty())
      return 1.0;

    if (Empty() || rhs.Empty())
      return 0.0;

    auto const & ls = m_tws;
    auto const & rs = rhs.GetTokenWeightPairs();

    ASSERT(std::is_sorted(ls.begin(), ls.end()), ());
    ASSERT(std::is_sorted(rs.begin(), rs.end()), ());

    std::vector<size_t> rsMatchTo(rs.size(), kInvalidIndex);

    size_t i = 0, j = 0;
    double dot = 0;
    while (i < ls.size() && j < rs.size())
    {
      if (ls[i].m_token < rs[j].m_token)
      {
        ++i;
      }
      else if (ls[i].m_token > rs[j].m_token)
      {
        ++j;
      }
      else
      {
        dot += ls[i].m_weight * rs[j].m_weight;
        rsMatchTo[j] = i;
        ++i;
        ++j;
      }
    }

    auto const ln = impl::SqrL2(ls, m_prefix);
    auto const rn = impl::SqrL2(rs);

    // This similarity metric assumes that prefix is not matched in the document.
    double const similarityNoPrefix = ln > 0 && rn > 0 ? dot / sqrt(ln) / sqrt(rn) : 0;

    if (!m_prefix)
      return similarityNoPrefix;

    double similarityWithPrefix = 0;

    auto const & prefix = *m_prefix;

    // Let's try to match prefix token with all tokens in the
    // document, and compute the best cosine distance.
    for (size_t j = 0; j < rs.size(); ++j)
    {
      auto const & tw = rs[j];
      if (!strings::StartsWith(tw.m_token.begin(), tw.m_token.end(), prefix.m_token.begin(),
                               prefix.m_token.end()))
      {
        continue;
      }

      auto const i = rsMatchTo[j];

      double nom = 0;
      double denom = 0;
      if (i == kInvalidIndex)
      {
        // If this document token is not matched with full tokens in a
        // query, we need to update it's weight in the cosine distance
        // - so we need to update correspondingly dot product and
        // vector norms of query and doc.

        // This is the hacky moment: weight of query prefix token may
        // be greater than the weight of the corresponding document
        // token, because the weight of the document token may be
        // unknown at the moment, and be set to some default value.
        // But this heuristic works nicely in practice.
        double const w = std::max(prefix.m_weight, tw.m_weight);
        auto const sqrW = w * w;
        double const l = std::max(0.0, ln - prefix.Sqr() + sqrW);
        double const r = std::max(0.0, rn - tw.Sqr() + sqrW);

        nom = dot + sqrW;
        denom = sqrt(l) * sqrt(r);
      }
      else
      {
        // If this document token is already matched with |i|-th full
        // token in a query - we here that completion of the prefix
        // token is the |i|-th token. So we need to update
        // correspondingly dot product and vector norm of the query.
        double const l = ln + 2 * ls[i].m_weight * prefix.m_weight;

        nom = dot + prefix.m_weight * tw.m_weight;
        denom = sqrt(l) * sqrt(rn);
      }

      if (denom > 0)
        similarityWithPrefix = std::max(similarityWithPrefix, nom / denom);
    }

    return std::max(similarityWithPrefix, similarityNoPrefix);
  }

  double Norm() const
  {
    double n = 0;
    for (auto const & tw : m_tws)
      n += tw.m_weight * tw.m_weight;
    if (m_prefix)
      n += m_prefix->m_weight * m_prefix->m_weight;
    return sqrt(n);
  }

  bool Empty() const { return m_tws.empty() && !m_prefix; }

private:
  template <typename T>
  friend std::string DebugPrint(QueryVec<T> const & qv)
  {
    return "QueryVec " + DebugPrint(qv.m_tws);
  }

  void Init() { impl::SortAndMerge(m_tws); }

  std::vector<TokenWeightPair> m_tws;
  boost::optional<TokenWeightPair> m_prefix;
};
}  // namespace search
<commit_msg>Review fixes.<commit_after>#pragma once

#include "base/assert.hpp"
#include "base/string_utils.hpp"

#include <algorithm>
#include <cmath>
#include <cstddef>
#include <sstream>
#include <string>
#include <utility>

#include <boost/optional.hpp>

namespace search
{
template <typename Token>
struct TokenWeightPair
{
  TokenWeightPair() = default;

  template <typename T>
  TokenWeightPair(T && token, double weight) : m_token(std::forward<T>(token)), m_weight(weight)
  {
  }

  bool operator<(TokenWeightPair const & rhs) const
  {
    if (m_token != rhs.m_token)
      return m_token < rhs.m_token;
    return m_weight < rhs.m_weight;
  }

  void Swap(TokenWeightPair & rhs)
  {
    m_token.swap(rhs.m_token);
    std::swap(m_weight, rhs.m_weight);
  }

  // Returns squared weight of the token-weight pair.
  double Sqr() const { return m_weight * m_weight; }

  Token m_token;
  double m_weight = 0;
};

template <typename Token>
std::string DebugPrint(TokenWeightPair<Token> const & tw)
{
  std::ostringstream os;
  os << "TokenWeightPair [ " << DebugPrint(tw.m_token) << ", " << tw.m_weight << " ]";
  return os.str();
}

namespace impl
{
// Accumulates weights of equal tokens in |tws|. Result is sorted by tokens.
template <typename Token>
void SortAndMerge(std::vector<TokenWeightPair<Token>> & tws)
{
  std::sort(tws.begin(), tws.end());
  size_t n = 0;
  for (size_t i = 0; i < tws.size(); ++i)
  {
    ASSERT_LESS_OR_EQUAL(n, i, ());
    if (n == 0 || tws[n - 1].m_token != tws[i].m_token)
    {
      tws[n].Swap(tws[i]);
      ++n;
    }
    else
    {
      tws[n - 1].m_weight += tws[i].m_weight;
    }
  }

  ASSERT_LESS_OR_EQUAL(n, tws.size(), ());
  tws.erase(tws.begin() + n, tws.end());
}

// Computes squared L2 norm of vector of tokens.
template <typename Token>
double SqrL2(std::vector<TokenWeightPair<Token>> const & tws)
{
  double sum = 0;
  for (auto const & tw : tws)
    sum += tw.Sqr();
  return sum;
}

// Computes squared L2 norm of vector of tokens + prefix token.
template <typename Token>
double SqrL2(std::vector<TokenWeightPair<Token>> const & tws,
             boost::optional<TokenWeightPair<Token>> const & prefix)
{
  double result = SqrL2(tws);
  return result + (prefix ? prefix->Sqr() : 0);
}
}  // namespace impl

// This class represents a document in a vector space of tokens.
template <typename Token>
class DocVec
{
public:
  using TokenWeightPair = TokenWeightPair<Token>;
  using TokenWeightPairs = std::vector<TokenWeightPair>;

  class Builder
  {
  public:
    template <typename T>
    void Add(T && token, double weight)
    {
      m_tws.emplace_back(std::forward<T>(token), weight);
    }

  private:
    friend class DocVec;

    TokenWeightPairs m_tws;
  };

  DocVec() = default;
  explicit DocVec(Builder && builder) : m_tws(std::move(builder.m_tws)) { Init(); }
  explicit DocVec(Builder const & builder) : m_tws(builder.m_tws) { Init(); }

  TokenWeightPairs const & GetTokenWeightPairs() const { return m_tws; }

  bool Empty() const { return m_tws.empty(); }

private:
  template <typename T>
  friend std::string DebugPrint(DocVec<T> const & dv)
  {
    return "DocVec " + DebugPrint(dv.m_tws);
  }

  void Init() { impl::SortAndMerge(m_tws); }

  TokenWeightPairs m_tws;
};

// This class represents a search query in a vector space of tokens.
template <typename Token>
class QueryVec
{
public:
  using TokenWeightPair = TokenWeightPair<Token>;
  using TokenWeightPairs = std::vector<TokenWeightPair>;

  class Builder
  {
  public:
    template <typename T>
    void AddFull(T && token, double weight)
    {
      m_tws.emplace_back(std::forward<T>(token), weight);
    }

    template <typename T>
    void SetPrefix(T && token, double weight)
    {
      m_prefix = TokenWeightPair(std::forward<T>(token), weight);
    }

  private:
    friend class QueryVec;

    TokenWeightPairs m_tws;
    boost::optional<TokenWeightPair> m_prefix;
  };

  QueryVec() = default;

  explicit QueryVec(Builder && builder)
    : m_tws(std::move(builder.m_tws)), m_prefix(std::move(builder.m_prefix))
  {
    Init();
  }

  explicit QueryVec(Builder const & builder) : m_tws(builder.m_tws), m_prefix(builder.m_prefix)
  {
    Init();
  }

  // Computes cosine distance between |*this| and |rhs|.
  double Similarity(DocVec<Token> const & rhs) const
  {
    size_t kInvalidIndex = std::numeric_limits<size_t>::max();

    if (Empty() && rhs.Empty())
      return 1.0;

    if (Empty() || rhs.Empty())
      return 0.0;

    auto const & ls = m_tws;
    auto const & rs = rhs.GetTokenWeightPairs();

    ASSERT(std::is_sorted(ls.begin(), ls.end()), ());
    ASSERT(std::is_sorted(rs.begin(), rs.end()), ());

    std::vector<size_t> rsMatchTo(rs.size(), kInvalidIndex);

    size_t i = 0, j = 0;
    double dot = 0;
    while (i < ls.size() && j < rs.size())
    {
      if (ls[i].m_token < rs[j].m_token)
      {
        ++i;
      }
      else if (ls[i].m_token > rs[j].m_token)
      {
        ++j;
      }
      else
      {
        dot += ls[i].m_weight * rs[j].m_weight;
        rsMatchTo[j] = i;
        ++i;
        ++j;
      }
    }

    auto const ln = impl::SqrL2(ls, m_prefix);
    auto const rn = impl::SqrL2(rs);

    // This similarity metric assumes that prefix is not matched in the document.
    double const similarityNoPrefix = ln > 0 && rn > 0 ? dot / sqrt(ln) / sqrt(rn) : 0;

    if (!m_prefix)
      return similarityNoPrefix;

    double similarityWithPrefix = 0;

    auto const & prefix = *m_prefix;

    // Let's try to match prefix token with all tokens in the
    // document, and compute the best cosine distance.
    for (size_t j = 0; j < rs.size(); ++j)
    {
      auto const & tw = rs[j];
      if (!strings::StartsWith(tw.m_token.begin(), tw.m_token.end(), prefix.m_token.begin(),
                               prefix.m_token.end()))
      {
        continue;
      }

      auto const i = rsMatchTo[j];

      double nom = 0;
      double denom = 0;
      if (i == kInvalidIndex)
      {
        // If this document token is not matched with full tokens in a
        // query, we need to update it's weight in the cosine distance
        // - so we need to update correspondingly dot product and
        // vector norms of query and doc.

        // This is the hacky moment: weight of query prefix token may
        // be greater than the weight of the corresponding document
        // token, because the weight of the document token may be
        // unknown at the moment, and be set to some default value.
        // But this heuristic works nicely in practice.
        double const w = std::max(prefix.m_weight, tw.m_weight);
        auto const sqrW = w * w;
        double const l = std::max(0.0, ln - prefix.Sqr() + sqrW);
        double const r = std::max(0.0, rn - tw.Sqr() + sqrW);

        nom = dot + sqrW;
        denom = sqrt(l) * sqrt(r);
      }
      else
      {
        // If this document token is already matched with |i|-th full
        // token in a query - we here that completion of the prefix
        // token is the |i|-th token. So we need to update
        // correspondingly dot product and vector norm of the query.
        double const l = ln + 2 * ls[i].m_weight * prefix.m_weight;

        nom = dot + prefix.m_weight * tw.m_weight;
        denom = sqrt(l) * sqrt(rn);
      }

      if (denom > 0)
        similarityWithPrefix = std::max(similarityWithPrefix, nom / denom);
    }

    return std::max(similarityWithPrefix, similarityNoPrefix);
  }

  double Norm() const
  {
    double n = 0;
    for (auto const & tw : m_tws)
      n += tw.m_weight * tw.m_weight;
    if (m_prefix)
      n += m_prefix->m_weight * m_prefix->m_weight;
    return sqrt(n);
  }

  bool Empty() const { return m_tws.empty() && !m_prefix; }

private:
  template <typename T>
  friend std::string DebugPrint(QueryVec<T> const & qv)
  {
    return "QueryVec " + DebugPrint(qv.m_tws);
  }

  void Init() { impl::SortAndMerge(m_tws); }

  std::vector<TokenWeightPair> m_tws;
  boost::optional<TokenWeightPair> m_prefix;
};
}  // namespace search
<|endoftext|>