text:
#include <Prismal/Renderer/CleanupQueue.hpp>
#include <Prismal/Renderer/GraphicsEngine.hpp>
#include <Prismal/Renderer/PipelineBuilder.hpp>
#include <Prismal/Renderer/Shader.hpp>
#include <Prismal/Renderer/Texture.hpp>
#include <Prismal/Renderer/VulkanHelpers.hpp>
#include <Prismal/Renderer/VulkanInitializers.hpp>

#include <Prismal/Compiler.hpp>
#include <Prismal/Core/AbstractApp.hpp>
#include <Prismal/Log.hpp>
#include <Prismal/Utils/Error.hpp>
#include <Prismal/Window/Window.hpp>

#include <Prismal/Assets/AssetDb.hpp>

#include <boost/algorithm/string.hpp>

#include <range/v3/view/enumerate.hpp>
#include <range/v3/view/iota.hpp>
#include <range/v3/view/zip.hpp>
#include <utility>

#include <SDL_vulkan.h>

#include <VkBootstrap.h>

namespace pr::render {
    namespace vki = vulkan::init;
    using vulkan::checkVkResult;
    using vulkan::PipelineBuilder;

    namespace {
        GraphicsEngine* currentPtr {nullptr};
    }

    GraphicsEngine::GraphicsEngine()
    {
        if (currentPtr)
            throw Error("Only one `GraphicsEngine` instance can be constructed!");
        currentPtr = this;

        // Register asset factories
        AssetDb::addAssetFactory(Material::create, static_cast<u16>(EAssetType::MaterialAsset));
        AssetDb::addAssetFactory(Mesh::create, static_cast<u16>(EAssetType::MeshAsset));
        AssetDb::addAssetFactory(Texture::create, static_cast<u16>(EAssetType::TextureAsset));
        AssetDb::addAssetFactory(Shader::create, static_cast<u16>(EAssetType::ShaderAsset));
    }

    GraphicsEngine* GraphicsEngine::current()
    {
        return currentPtr;
    }

    void GraphicsEngine::init()
    {
        u32 windowFlags = SDL_WINDOW_VULKAN;
        Window::init(windowFlags);
        {
            i32 w, h;
            Window::getDrawSize(&w, &h);
            state.swap.target.extent.width = w;
            state.swap.target.extent.height = h;
        }

        initVulkan();
        initSwapchain();
        initCommands();
        initSwapchainRenderPass();
        initSwapchainFramebuffers();
        initOffscreenRenderPass();
        initOffscreenFramebuffers();
        initSyncObjects();
        initSamplers();
        initGlobalDescriptors();
        initPbrDescriptors();
        initPipelines();

        loadMeshes();

        isInit = true;
    }

    void GraphicsEngine::cleanup()
    {
        if (!isInit)
            return;
        // Wait for all operations to complete
        vkDeviceWaitIdle(state.device);

        CleanupQueue::flush();

        // Destroy allocator
        vmaDestroyAllocator(state.allocator);

        // Clean up swapchain
        vkDestroySwapchainKHR(state.device, state.swap.swapchain, nullptr);

        // Clean up core Vulkan objects
        vkDestroyDevice(state.device, nullptr);
        vkDestroySurfaceKHR(state.instance, state.surface, nullptr);
        vkb::destroy_debug_utils_messenger(state.instance, state.debugMessenger);

        vkDestroyInstance(state.instance, nullptr);

        // Cleanup external resources
        Window::cleanup();
        currentPtr = nullptr;
        isInit = false;
    }

    void GraphicsEngine::draw()
    {
        auto& frame = currentFrame();

        checkVkResult(vkWaitForFences(state.device, 1, &frame.renderFence, VK_TRUE, 1000000000));
        checkVkResult(vkResetFences(state.device, 1, &frame.renderFence));

        u32 nextImageIdx;
        checkVkResult(vkAcquireNextImageKHR(state.device,
            state.swap.swapchain,
            1000000000,
            frame.presentSemaphore,
            nullptr,
            &nextImageIdx));

        checkVkResult(vkResetCommandBuffer(frame.mainCommandBuffer, 0));

        auto cmd = frame.mainCommandBuffer;
        auto beginInfo = vki::commandBufferBegin(true);

        checkVkResult(vkBeginCommandBuffer(cmd, &beginInfo));
        VkClearValue clearColor;
        clearColor.color = {0.5f, 0.5f, 0.5f, 1.0f};

        VkClearValue clearDepth;
        clearDepth.depthStencil.depth = 1.0f;

        VkClearValue clearValues[] = {clearColor, clearDepth};

        auto rpBegin = vki::renderPassBeginInfo(state.swap.target, nextImageIdx, clearValues, 2);
        vkCmdBeginRenderPass(cmd, &rpBegin, VK_SUBPASS_CONTENTS_INLINE);

        VkDeviceSize offset = 0;

        state.camera.setPerspective(70.0f,
            f32(state.swap.target.extent.width) / f32(state.swap.target.extent.height),
            0.1f,
            100.0f);
        GPUCameraData cameraData {
            .view = state.camera.matrices.view,
            .proj = state.camera.matrices.perspective,
            .viewPos = -state.camera.position(),
        };
        frame.cameraBuffer.uploadData(&cameraData, sizeof(GPUCameraData));

        GPURenderableData pushConstants {};

        {
            auto& l = state.scene.lights;
            l.resize(4);
            // Front
            l[0] = GPULight::createPointLight(FVec3(100.0f), FVec3(-10.0f, 10.0f, -10.0f));
            l[1] = GPULight::createPointLight(FVec3(100.0f), FVec3(10.0f, 10.0f, 10.0f));
            l[2] = GPULight::createPointLight(FVec3(100.0f), FVec3(-10.0f, -10.0f, 10.0f));
            l[3] = GPULight::createPointLight(FVec3(100.0f), FVec3(10.0f, -10.0f, -10.0f));
        }

        i32 lightsCount = static_cast<i32>(state.scene.lights.size());
        frame.lightsStorageBuffer.uploadData(state.scene.lights.data(),
            state.scene.lights.size() * sizeof(GPULight));

        auto& sceneParams = state.scene.params;
        sceneParams.ambientTint = FVec4(1.0f);
        sceneParams.sunDirection = FVec4(1, 1, 1, 1);
        sceneParams.sunColor = FVec4(1.0f);
        sceneParams.lightCount = lightsCount;
        {
            u64 o = AllocatedBuffer::padUniformBufferSize(sizeof(GPUSceneData)) * frameNumber;
            state.scene.paramsBuffer.uploadData(&sceneParams, sizeof(sceneParams), o);
        }

        Material* lastMaterial {nullptr};
        for (auto& r : state.scene.renderables)
        {
            if (r->material != lastMaterial)
            {
                lastMaterial = r->material;
                vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, r->material->pipeline);
                vkCmdBindDescriptorSets(cmd,
                    VK_PIPELINE_BIND_POINT_GRAPHICS,
                    r->material->layout,
                    0,
                    1,
                    &frame.globalDescriptor,
                    0,
                    nullptr);
            }

            {
                auto modelMat = r->transform.toMatrix();
                pushConstants.modelMat = modelMat;
                vkCmdPushConstants(cmd,
                    lastMaterial->layout,
                    VK_SHADER_STAGE_VERTEX_BIT,
                    0,
                    sizeof(pushConstants),
                    &pushConstants);
            }

            if (auto mesh = r->mesh)
            {
                for (auto& mc : mesh->components)
                {
                    vkCmdBindVertexBuffers(cmd, 0, 1, &mc.vertexBuffer.buffer, &offset);
                    vkCmdBindIndexBuffer(cmd, mc.indexBuffer.buffer, offset, VK_INDEX_TYPE_UINT32);
                    vkCmdDrawIndexed(cmd, mc.indexCount, 1, 0, 0, 0);
                }
            }
        }
        vkCmdEndRenderPass(cmd);

        checkVkResult(vkEndCommandBuffer(cmd));

        VkPipelineStageFlags waitStage = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
        auto submit = vki::submitInfo(&cmd, 1);
        submit.pWaitDstStageMask = &waitStage;
        submit.waitSemaphoreCount = 1;
        submit.pWaitSemaphores = &frame.presentSemaphore;
        submit.signalSemaphoreCount = 1;
        submit.pSignalSemaphores = &frame.renderSemaphore;

        checkVkResult(
            vkQueueSubmit(state.queues[ERendererQueueType::Graphics].queue, 1, &submit, frame.renderFence));

        // Present the rendered image
        VkPresentInfoKHR presentInfo = {};
        presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
        presentInfo.pNext = nullptr;
        presentInfo.pSwapchains = &state.swap.swapchain;
        presentInfo.swapchainCount = 1;
        presentInfo.pWaitSemaphores = &frame.renderSemaphore;
        presentInfo.waitSemaphoreCount = 1;
        presentInfo.pImageIndices = &nextImageIdx;

        checkVkResult(vkQueuePresentKHR(state.queues[ERendererQueueType::Present].queue, &presentInfo));

        frameNumber = (frameNumber + 1) % FRAME_OVERLAP;
    }

    VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
        VkDebugUtilsMessageTypeFlagsEXT /* messageType */,
        const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* /* pUserData */)
    {
        switch (messageSeverity)
        {
        case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT:
            PR_ENGINE_DEBUG_TAG("Vulkan", "Validation: {}", pCallbackData->pMessage);
            break;
        case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT:
            PR_ENGINE_INFO_TAG("Vulkan", "Validation: {}", pCallbackData->pMessage);
            break;
        case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT:
            PR_ENGINE_WARN_TAG("Vulkan", "Validation: {}", pCallbackData->pMessage);
            break;
        case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
        case VK_DEBUG_UTILS_MESSAGE_SEVERITY_FLAG_BITS_MAX_ENUM_EXT:
            PR_ENGINE_ERROR_TAG("Vulkan", "Validation: {}", pCallbackData->pMessage);
            break;
        }
        return VK_FALSE;
    }

    void GraphicsEngine::initVulkan()
    {
        auto appName = AbstractApp::current()->getAppName();
        vkb::InstanceBuilder builder;
        auto instanceRet = builder.set_app_name(appName.data())
                               .set_engine_name("Prismal")
                               .request_validation_layers(true)
                               .require_api_version(1, 1, 0)
                               .set_debug_callback(debugCallback)
                               .build();
        vkb::Instance vkbInst = instanceRet.value();
        state.instance = vkbInst.instance;
        state.debugMessenger = vkbInst.debug_messenger;

        SDL_Vulkan_CreateSurface(Window::handle(), state.instance, &state.surface);

        VkPhysicalDeviceFeatures requiredFeatures = {};
        requiredFeatures.geometryShader = VK_TRUE;

        vkb::PhysicalDeviceSelector gpuSelector {vkbInst};
        vkb::PhysicalDevice vkbGpu = gpuSelector.set_minimum_version(1, 1)
                                         .set_surface(state.surface)
                                         .prefer_gpu_device_type(vkb::PreferredDeviceType::discrete)
                                         .set_required_features(requiredFeatures)
                                         .select()
                                         .value();

        vkb::DeviceBuilder deviceBuilder {vkbGpu};
        vkb::Device vkbDevice = deviceBuilder.build().value();

        state.device = vkbDevice.device;
        state.gpu = vkbGpu.physical_device;

        state.queues[ERendererQueueType::Graphics].queue
            = vkbDevice.get_queue(vkb::QueueType::graphics).value();
        state.queues[ERendererQueueType::Graphics].index
            = vkbDevice.get_queue_index(vkb::QueueType::graphics).value();

        state.queues[ERendererQueueType::Present].queue
            = vkbDevice.get_queue(vkb::QueueType::present).value();
        state.queues[ERendererQueueType::Present].index
            = vkbDevice.get_queue_index(vkb::QueueType::present).value();

        // Compute queue
        {
            auto qd = vkbDevice.get_dedicated_queue(vkb::QueueType::compute);
            auto qid = vkbDevice.get_dedicated_queue_index(vkb::QueueType::compute);
            if (qd && qid)
            {
                state.queues[ERendererQueueType::Compute].queue = qd.value();
                state.queues[ERendererQueueType::Compute].index = qid.value();
            }
            else
            {
                auto q = vkbDevice.get_queue(vkb::QueueType::compute);
                auto qi = vkbDevice.get_queue_index(vkb::QueueType::compute);
                state.queues[ERendererQueueType::Compute].queue = q.value();
                state.queues[ERendererQueueType::Compute].index = qi.value();
            }
        }

        // Transfer queue
        {
            auto qd = vkbDevice.get_dedicated_queue(vkb::QueueType::transfer);
            auto qid = vkbDevice.get_dedicated_queue_index(vkb::QueueType::transfer);
            if (qd && qid)
            {
                state.queues[ERendererQueueType::Transfer].queue = qd.value();
                state.queues[ERendererQueueType::Transfer].index = qid.value();
            }
            else
            {
                auto q = vkbDevice.get_queue(vkb::QueueType::transfer);
                auto qi = vkbDevice.get_queue_index(vkb::QueueType::transfer);
                state.queues[ERendererQueueType::Transfer].queue = q.value();
                state.queues[ERendererQueueType::Transfer].index = qi.value();
            }
        }

        VmaAllocatorCreateInfo allocatorInfo = {};
        allocatorInfo.physicalDevice = state.gpu;
        allocatorInfo.device = state.device;
        allocatorInfo.instance = state.instance;
        vmaCreateAllocator(&allocatorInfo, &state.allocator);

        // Fetch and cache GPU properties
        vkGetPhysicalDeviceProperties(state.gpu, &state.gpuProperties);
    }

    void GraphicsEngine::initSwapchain()
    {
        vkb::SwapchainBuilder swapchainBuilder {state.gpu, state.device, state.surface};
        vkb::Swapchain vkbSwapchain = swapchainBuilder.use_default_format_selection()
                                          .set_desired_present_mode(VK_PRESENT_MODE_MAILBOX_KHR)
                                          .set_desired_extent(state.swap.target.extent.width,
                                              state.swap.target.extent.height)
                                          .build()
                                          .value();
        state.swap.swapchain = vkbSwapchain.swapchain;

        // Get images
        {
            auto v = vkbSwapchain.get_images().value();
            state.swap.target.images.insert(state.swap.target.images.begin(), v.begin(), v.end());
        }

        // Get image views
        {
            auto v = vkbSwapchain.get_image_views().value();
            state.swap.target.imageViews.insert(state.swap.target.imageViews.begin(),
                v.begin(),
                v.end());
        }

        // Image format
        state.swap.target.imageFormat = vkbSwapchain.image_format;
    }

    void GraphicsEngine::initCommands()
    {
        auto cmdPoolInfo = vki::commandPoolCreateInfo(state.queues[ERendererQueueType::Graphics].index,
            true);
        checkVkResult(vkCreateCommandPool(state.device, &cmdPoolInfo, nullptr, &state.cmd.gfxPool));

        for (auto t : ALL_RENDERER_QUEUE_TYPES)
        {
            auto info = vki::commandPoolCreateInfo(state.queues[t].index, false);
            auto& ctx = immediateSubmitContext[t];
            checkVkResult(vkCreateCommandPool(state.device, &info, nullptr, &ctx.commandPool));
            CleanupQueue::push(
                [=, this] { vkDestroyCommandPool(state.device, ctx.commandPool, nullptr); });
        }

        CleanupQueue::push(
            [=, this] { vkDestroyCommandPool(state.device, state.cmd.gfxPool, nullptr); });

        auto allocInfo = vki::commandBufferAllocateInfo(state.cmd.gfxPool);
        for (auto& frame : state.frames)
        {
            checkVkResult(vkAllocateCommandBuffers(state.device, &allocInfo, &frame.mainCommandBuffer));
        }
    }

    void GraphicsEngine::initSwapchainRenderPass()
    {
        auto colorAttachment = vki::attachmentDescription(state.swap.target.imageFormat,
            VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
        auto colorRef = vki::attachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);

        VkAttachmentDescription attachments[] = {colorAttachment};

        auto subpass = vki::subpassDescriptionGfx(&colorRef, nullptr);

        auto renderPassInfo = vki::renderPassCreateInfo(attachments, &subpass, 1);

        checkVkResult(
            vkCreateRenderPass(state.device, &renderPassInfo, nullptr, &state.swap.target.renderPass));

        CleanupQueue::push(
            [=, this] { vkDestroyRenderPass(state.device, state.swap.target.renderPass, nullptr); });
    }

    void GraphicsEngine::initSwapchainFramebuffers()
    {
        auto& imgViews = state.swap.target.imageViews;

        auto& fbs = state.swap.target.framebuffers;
        fbs.resize(imgViews.size());

        auto fbInfo = vki::framebufferCreateInfo(state.swap.target.renderPass,
            nullptr,
            1,
            state.swap.target.extent);
        for (auto i : ranges::views::zip(imgViews, fbs))
        {
            auto& v = i.first;
            auto& fb = i.second;
            VkImageView attachments[1];

            attachments[0] = v;
            //            attachments[1] = state.swap.target.depthImageView;

            fbInfo.pAttachments = attachments;
            checkVkResult(vkCreateFramebuffer(state.device, &fbInfo, nullptr, &fb));

            CleanupQueue::push([=, this] {
                vkDestroyFramebuffer(state.device, i.second, nullptr);
                vkDestroyImageView(state.device, i.first, nullptr);
            });
        }
    }

    void GraphicsEngine::initOffscreenRenderPass()
    {
        auto& rt = state.offscreen.target;
        rt.imageFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
        rt.depthFormat = VK_FORMAT_D32_SFLOAT;
        rt.extent = state.swap.target.extent;

        // Init depth buffering
        {
            VkExtent3D depthImageExtent {
                .width = rt.extent.width,
                .height = rt.extent.height,
                .depth = 1,
            };
            auto dimgInfo = vki::imageCreateInfo(rt.depthFormat,
                VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
                depthImageExtent);

            VmaAllocationCreateInfo allocInfo {
                .usage = VMA_MEMORY_USAGE_GPU_ONLY,
                .requiredFlags = VkMemoryPropertyFlags(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT),
            };
            AllocatedImage dimg {
                .width = depthImageExtent.width,
                .height = depthImageExtent.height,
            };
            vmaCreateImage(state.allocator, &dimgInfo, &allocInfo, &dimg.image, &dimg.allocation, nullptr);

            rt.depthImage = dimg;
            auto viewInfo = vki::imageViewCreateInfo(rt.depthFormat,
                dimg.image,
                VK_IMAGE_ASPECT_DEPTH_BIT);
            checkVkResult(vkCreateImageView(state.device, &viewInfo, nullptr, &rt.depthImageView));

            CleanupQueue::push([=, this] {
                auto& tmpRt = state.offscreen.target;
                vkDestroyImageView(state.device, tmpRt.depthImageView, nullptr);
                vmaDestroyImage(state.allocator, tmpRt.depthImage->image, tmpRt.depthImage->allocation);
            });
        }

        auto colorAttachment = vki::attachmentDescription(state.offscreen.target.imageFormat,
            VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
        auto colorRef = vki::attachmentReference(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);

        auto depthAttachment = vki::attachmentDescription(state.offscreen.target.depthFormat,
            VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
        auto depthRef = vki::attachmentReference(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);

        VkAttachmentDescription attachments[] = {colorAttachment, depthAttachment};

        auto subpass = vki::subpassDescriptionGfx(&colorRef, &depthRef);

        auto renderPassInfo = vki::renderPassCreateInfo(attachments, &subpass, 2);

        checkVkResult(
            vkCreateRenderPass(state.device, &renderPassInfo, nullptr, &state.offscreen.target.renderPass));

        CleanupQueue::push([=, this] {
            vkDestroyRenderPass(state.device, state.offscreen.target.renderPass, nullptr);
        });
    }

    void GraphicsEngine::initOffscreenFramebuffers()
    {
        auto width = state.offscreen.target.extent.width;
        auto height = state.offscreen.target.extent.height;
        auto colorFmt = state.offscreen.target.imageFormat;

        const auto frameCount = state.swap.target.imageViews.size();
        auto& fbs = state.offscreen.target.framebuffers;
        fbs.resize(frameCount);

        auto fbInfo = vki::framebufferCreateInfo(state.offscreen.target.renderPass,
            nullptr,
            2,
            state.swap.target.extent);

        for (auto i = 0; i < frameCount; ++i)
        {
            auto img = AllocatedImage::create(width,
                height,
                colorFmt,
                VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
                VMA_MEMORY_USAGE_GPU_ONLY);

            auto viewInfo = vki::imageViewCreateInfo(colorFmt, img.image, VK_IMAGE_ASPECT_COLOR_BIT);
            VkImageView v;
            checkVkResult(vkCreateImageView(state.device, &viewInfo, nullptr, &v));

            state.offscreen.target.images.push_back(img.image);
            state.offscreen.target.imageViews.push_back(v);

            auto& fb = fbs[i];
            VkImageView attachments[2];
            attachments[0] = v;
            attachments[1] = state.offscreen.target.depthImageView;

            fbInfo.pAttachments = attachments;
            checkVkResult(vkCreateFramebuffer(state.device, &fbInfo, nullptr, &fb));

            CleanupQueue::push([=, this] {
                vkDestroyFramebuffer(state.device, fb, nullptr);
                vkDestroyImageView(state.device, v, nullptr);
                img.cleanup();
            });
        }
    }

    void GraphicsEngine::initSyncObjects()
    {
        auto fenceInfo = vki::fenceCreateInfo();
        auto signaledFenceInfo = vki::fenceCreateInfo(true);
        auto semaphoreInfo = vki::semaphoreCreateInfo();

        for (auto t : ALL_RENDERER_QUEUE_TYPES)
        {
            auto& ctx = immediateSubmitContext[t];
            checkVkResult(vkCreateFence(state.device, &fenceInfo, nullptr, &ctx.fence));
            CleanupQueue::push([=, this] { vkDestroyFence(state.device, ctx.fence, nullptr); });
        }

        for (auto& frame : state.frames)
        {
            checkVkResult(vkCreateFence(state.device, &signaledFenceInfo, nullptr, &frame.renderFence));

            checkVkResult(
                vkCreateSemaphore(state.device, &semaphoreInfo, nullptr, &frame.renderSemaphore));
            checkVkResult(
                vkCreateSemaphore(state.device, &semaphoreInfo, nullptr, &frame.renderOffscreenSemaphore));
            checkVkResult(
                vkCreateSemaphore(state.device, &semaphoreInfo, nullptr, &frame.presentSemaphore));

            CleanupQueue::push([=, this] {
                vkDestroyFence(state.device, frame.renderFence, nullptr);
                vkDestroySemaphore(state.device, frame.renderSemaphore, nullptr);
                vkDestroySemaphore(state.device, frame.renderOffscreenSemaphore, nullptr);
                vkDestroySemaphore(state.device, frame.presentSemaphore, nullptr);
            });
        }
    }

    void GraphicsEngine::initGlobalDescriptors()
    {
        u64 sceneParamsBufSize = FRAME_OVERLAP
                                 * AllocatedBuffer::padUniformBufferSize(sizeof(GPUSceneData));
        state.scene.paramsBuffer = AllocatedBuffer::create(sceneParamsBufSize,
            VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
            VMA_MEMORY_USAGE_CPU_TO_GPU);

        CleanupQueue::push([=, this] { state.scene.paramsBuffer.cleanup(); });

        auto camBufBinding = vki::descriptorSetLayoutBinding(0,
            VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
            VK_SHADER_STAGE_VERTEX_BIT);
        auto sceneBufBinding = vki::descriptorSetLayoutBinding(1,
            VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
            VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);

        auto lightsStorageBufBinding = vki::descriptorSetLayoutBinding(2,
            VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
            VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT);

        const VkDescriptorSetLayoutBinding bindings[] = {
            camBufBinding,
            sceneBufBinding,
            lightsStorageBufBinding,
        };
        auto setInfo = vki::descriptorSetLayoutCreateInfo(bindings, PR_CARRAY_SIZE(bindings));
        checkVkResult(
            vkCreateDescriptorSetLayout(state.device, &setInfo, nullptr, &state.descriptor.globalLayout));

        const VkDescriptorPoolSize poolSizes[] = {
            {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 64},
            {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 64},
            {VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 64},
        };

        VkDescriptorPoolCreateInfo poolInfo {
            .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
            .pNext = nullptr,
            .flags = 0u,
            .maxSets = 128 * PR_CARRAY_SIZE(poolSizes),
            .poolSizeCount = PR_CARRAY_SIZE(poolSizes),
            .pPoolSizes = poolSizes,
        };
        checkVkResult(vkCreateDescriptorPool(state.device, &poolInfo, nullptr, &state.descriptor.pool));
        CleanupQueue::push([=, this] {
            vkDestroyDescriptorSetLayout(state.device, state.descriptor.globalLayout, nullptr);
            vkDestroyDescriptorPool(state.device, state.descriptor.pool, nullptr);
        });

        for (auto it : state.frames | ranges::views::enumerate)
        {
            auto i = it.first;
            auto& frame = it.second;
            frame.cameraBuffer = AllocatedBuffer::create(sizeof(GPUCameraData),
                VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
                VMA_MEMORY_USAGE_CPU_TO_GPU);

            u64 lightsBufferSize = sizeof(i32) + (sizeof(GPULight) * MAX_GPU_LIGHTS);
            frame.lightsStorageBuffer = AllocatedBuffer::create(lightsBufferSize,
                VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
                VMA_MEMORY_USAGE_CPU_TO_GPU);

            CleanupQueue::push([=] {
                frame.cameraBuffer.cleanup();
                frame.lightsStorageBuffer.cleanup();
            });

            const VkDescriptorSetLayout setLayouts[] = {
                state.descriptor.globalLayout,
            };
            auto allocInfo = vki::descriptorSetAllocateInfo(state.descriptor.pool,
                PR_CARRAY_SIZE(setLayouts),
                setLayouts);
            checkVkResult(vkAllocateDescriptorSets(state.device, &allocInfo, &frame.globalDescriptor));

            auto camBufInfo = vki::descriptorBufferInfo(frame.cameraBuffer.buffer,
                sizeof(GPUCameraData));
            auto sceneBufInfo = vki::descriptorBufferInfo(state.scene.paramsBuffer.buffer,
                sizeof(GPUSceneData),
                AllocatedBuffer::padUniformBufferSize(sizeof(GPUSceneData)) * i);
            auto lightsBufInfo = vki::descriptorBufferInfo(frame.lightsStorageBuffer.buffer,
                lightsBufferSize);

            auto camBufWrite = vki::writeDescriptorSetBuffer(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
                frame.globalDescriptor,
                0,
                1,
                &camBufInfo);
            auto sceneBufWrite = vki::writeDescriptorSetBuffer(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
                frame.globalDescriptor,
                1,
                1,
                &sceneBufInfo);
            auto lightsBufWrite = vki::writeDescriptorSetBuffer(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
                frame.globalDescriptor,
                2,
                1,
                &lightsBufInfo);
            VkWriteDescriptorSet setWrites[] = {camBufWrite, sceneBufWrite, lightsBufWrite};
            vkUpdateDescriptorSets(state.device, PR_CARRAY_SIZE(setWrites), setWrites, 0, nullptr);
        }
    }

    void GraphicsEngine::initPbrDescriptors()
    {
        auto albedoTexBinding = vki::descriptorSetLayoutBinding(0,
            VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
            VK_SHADER_STAGE_FRAGMENT_BIT);
        auto roughnessTexBinding = vki::descriptorSetLayoutBinding(1,
            VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
            VK_SHADER_STAGE_FRAGMENT_BIT);
        auto metallicTexBinding = vki::descriptorSetLayoutBinding(2,
            VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
            VK_SHADER_STAGE_FRAGMENT_BIT);
        auto occlusionTexBinding = vki::descriptorSetLayoutBinding(3,
            VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
            VK_SHADER_STAGE_FRAGMENT_BIT);

        const VkDescriptorSetLayoutBinding bindings[] = {
            albedoTexBinding,
            roughnessTexBinding,
            metallicTexBinding,
            occlusionTexBinding,
        };

        auto setInfo = vki::descriptorSetLayoutCreateInfo(bindings, PR_CARRAY_SIZE(bindings));

        checkVkResult(vkCreateDescriptorSetLayout(state.device,
            &setInfo,
            nullptr,
            &state.descriptor.pbrTexturesLayout));

        CleanupQueue::push([this] {
            vkDestroyDescriptorSetLayout(state.device, state.descriptor.pbrTexturesLayout, nullptr);
        });
    }

    void GraphicsEngine::initPipelines()
    {
        auto vertexDescription = MeshVertex::vertexDescription();
        auto pushConstants = vki::pushConstantRange(0,
            sizeof(GPURenderableData),
            VK_SHADER_STAGE_VERTEX_BIT);

        const VkDescriptorSetLayout setLayouts[] = {
            state.descriptor.globalLayout,
            state.descriptor.pbrTexturesLayout,
        };
        auto layoutInfo = vki::pipelineLayoutCreateInfo(&pushConstants, 1);
        layoutInfo.setLayoutCount = PR_CARRAY_SIZE(setLayouts);
        layoutInfo.pSetLayouts = setLayouts;
        checkVkResult(
            vkCreatePipelineLayout(state.device, &layoutInfo, nullptr, &state.scene.meshLayout));

        AssetDb::loadAssetDeferred("Engine/SH_Mesh_V.pra", AssetKey {"Engine/SH_Mesh_V"});
        AssetDb::loadAssetDeferred("Engine/SH_LitPhysical_F.pra", AssetKey {"Engine/SH_LitPhysical_F"});
        AssetDb::loadAssetDeferred("Engine/M_LitPhysical.pra", AssetKey {"Engine/M_LitPhysical"});

        {
            auto cb = [=, this] {
                vkDestroyPipelineLayout(state.device, state.scene.meshLayout, nullptr);
            };
            CleanupQueue::push(cb);
        }
    }

    void GraphicsEngine::initSamplers()
    {
        auto nearestInfo = vki::samplerCreateInfo(VK_FILTER_NEAREST);
        vkCreateSampler(state.device, &nearestInfo, nullptr, &state.samplers.nearest);

        auto linearInfo = vki::samplerCreateInfo(VK_FILTER_LINEAR);
        vkCreateSampler(state.device, &linearInfo, nullptr, &state.samplers.linear);

        CleanupQueue::push([this] {
            vkDestroySampler(state.device, state.samplers.linear, nullptr);
            vkDestroySampler(state.device, state.samplers.nearest, nullptr);
        });
    }

    void GraphicsEngine::loadMeshes()
    {
        AssetDb::loadAssetDeferred("Engine/S_UnitSphere.pra", AssetKey {"Engine/S_UnitSphere"});
    }

    FrameData& GraphicsEngine::currentFrame()
    {
        return state.frames[frameNumber];
    }

    Mesh* GraphicsEngine::getMesh(AssetKey key)
    {
        return dynamic_cast<Mesh*>(AssetDb::getAsset(key));
    }

    Material* GraphicsEngine::getMaterial(AssetKey key)
    {
        return dynamic_cast<Material*>(AssetDb::getAsset(key));
    }

    Texture* GraphicsEngine::getTexture(AssetKey key)
    {
        return dynamic_cast<Texture*>(AssetDb::getAsset(key));
    }

    WeakPtr<Renderable3D> GraphicsEngine::addRenderable3D(AssetKey meshKey, AssetKey materialKey,
        m::Transform3D transform, i16 priority)
    {
        auto ptr = SharedPtr<Renderable3D>(new Renderable3D {
            .mesh = getMesh(meshKey),
            .material = getMaterial(materialKey),
            .transform = std::move(transform),
            .priority = priority,
        });
        auto& arr = state.scene.renderables;
        auto pos = std::lower_bound(arr.begin(),
            arr.end(),
            priority,
            [](const SharedPtr<Renderable3D>& lhs, i16 rhs) { return lhs->priority < rhs; });
        arr.insert(pos, ptr);
        return ptr;
    }

    void GraphicsEngine::immediateSubmit(Function<void(VkCommandBuffer)>&& fn,
        ERendererQueueType queueType)
    {
        auto cmdAllocInfo = vki::commandBufferAllocateInfo(immediateSubmitContext[queueType].commandPool,
            1);

        VkCommandBuffer cmd;
        checkVkResult(vkAllocateCommandBuffers(state.device, &cmdAllocInfo, &cmd));

        auto beginInfo = vki::commandBufferBegin(true);
        checkVkResult(vkBeginCommandBuffer(cmd, &beginInfo));
        {
            fn(cmd);
        }
        checkVkResult(vkEndCommandBuffer(cmd));

        auto submit = vki::submitInfo(&cmd, 1);
        checkVkResult(vkQueueSubmit(state.queues[queueType].queue,
            1,
            &submit,
            immediateSubmitContext[queueType].fence));

        vkWaitForFences(state.device, 1, &immediateSubmitContext[queueType].fence, true, 9999999999);
        vkResetFences(state.device, 1, &immediateSubmitContext[queueType].fence);

        vkResetCommandPool(state.device, immediateSubmitContext[queueType].commandPool, 0);
    }

    void GraphicsEngine::waitIdle() const
    {
        vkDeviceWaitIdle(state.device);
    }

} // namespace pr::render

max_stars_repo_name: PrismalEngine/prismal-engine

max_issues_repo_name: PrismalEngine/prismal-engine

max_forks_repo_name: PrismalEngine/prismal-engine


text:
// Boost.Geometry (aka GGL, Generic Geometry Library)

// Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
// Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
// Copyright (c) 2009-2012 Mateusz Loskot, London, UK.

// This file was modified by Oracle on 2014.
// Modifications copyright (c) 2014 Oracle and/or its affiliates.

// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.

// Use, modification and distribution is subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle

#ifndef BOOST_GEOMETRY_VIEWS_DETAIL_NORMALIZED_VIEW_HPP
#define BOOST_GEOMETRY_VIEWS_DETAIL_NORMALIZED_VIEW_HPP

#include <boost/range/begin.hpp>
#include <boost/range/end.hpp>
#include <boost/range/iterator.hpp>
#include <boost/mpl/if.hpp>
#include <boost/type_traits/is_const.hpp>
#include <boost/geometry/views/detail/range_type.hpp>
#include <boost/geometry/views/reversible_view.hpp>
#include <boost/geometry/views/closeable_view.hpp>

namespace boost { namespace geometry {

#ifndef DOXYGEN_NO_DETAIL

namespace detail {

template <typename Geometry>
struct normalized_view
{
    static const bool is_const = boost::is_const<Geometry>::value;

    //typedef typename ring_type<Geometry>::type ring_type;

    typedef typename detail::range_type<Geometry>::type range_type;

    typedef typename
        boost::mpl::if_c
            <
                is_const,
                range_type const,
                range_type
            >::type range;

    typedef typename
        reversible_view
            <
                range,
                order_as_direction
                    <
                        geometry::point_order<Geometry>::value
                    >::value
            >::type reversible_type;

    typedef typename
        boost::mpl::if_c
            <
                is_const,
                reversible_type const,
                reversible_type
            >::type reversible;

    typedef typename
        closeable_view
            <
                reversible,
                geometry::closure<Geometry>::value
            >::type closeable_type;

    typedef typename
        boost::mpl::if_c
            <
                is_const,
                closeable_type const,
                closeable_type
            >::type closeable;

    explicit inline normalized_view(range & r)
        : m_reversible(r)
        , m_closeable(m_reversible)
    {}

    typedef typename boost::range_iterator<closeable>::type iterator;
    typedef typename boost::range_const_iterator<closeable>::type const_iterator;

    inline const_iterator begin() const { return boost::begin(m_closeable); }
    inline const_iterator end() const { return boost::end(m_closeable); }

    inline iterator begin() { return boost::begin(m_closeable); }
    inline iterator end() { return boost::end(m_closeable); }

private:
    reversible_type m_reversible;
    closeable_type m_closeable;
};

} // namespace detail

#endif // DOXYGEN_NO_DETAIL

}} // namespace boost::geometry

#endif // BOOST_GEOMETRY_VIEWS_DETAIL_NORMALIZED_VIEW_HPP

ext: hpp

max_stars_repo_name: cooparation/caffe-android

max_issues_repo_name: cooparation/caffe-android

max_forks_repo_name: cooparation/caffe-android


text:
/*
 * bus_service.cpp
 *
 *  Created on: 16 окт. 2016 г.
 *      Author: sergey.fedorov
 */

#include <wire/bus/bus_service.hpp>
#include <wire/bus/bus_options.hpp>
#include <wire/bus/bus_impl.hpp>

#include <wire/core/connector.hpp>
#include <wire/core/adapter.hpp>

#include <wire/util/make_unique.hpp>

#include <boost/program_options.hpp>

namespace wire {
namespace svc {

struct bus_service::impl {
    ::std::string           name_;

    core::adapter_ptr       bus_adapter_;
    core::adapter_ptr       publisher_adapter_;
    bus::bus_registry_prx   registry_;

    impl(::std::string const& name)
        : name_{name} {}

    void
    start(core::connector_ptr cnctr)
    {
        namespace po = ::boost::program_options;
        bus_options opts;
        po::options_description opts_desc{"Bus options"};
        opts_desc.add_options()
            ((name_ + ".id").c_str(),
                po::value<core::identity>(&opts.bus_registry_id)->default_value("bus.registry"_wire_id),
                "Identity for bus registry object")
            ((name_ + ".adapter").c_str(),
                po::value<::std::string>(&opts.bus_adapter_category)->default_value("wire.bus"),
                "Category and replica name for bus adapter")
            ((name_ + ".endpoints").c_str(),
                po::value<core::endpoint_list>(&opts.bus_endpoints)->required(),
                "Endpoints for bus adapter")
            ((name_ + ".category").c_str(),
                po::value<::std::string>(&opts.bus_category)->default_value("bus"),
                "Category for bus objects")
            ((name_ + ".publisher.adapter").c_str(),
                po::value<::std::string>(&opts.publisher_adapter_category)->default_value("wire.bus.publisher"),
                "Category and replica name for publisher objects adapter")
            ((name_ + ".publisher.endpoints").c_str(),
                po::value<core::endpoint_list>(&opts.publisher_endpoints),
                "Endpoints for publiser objects adapter")
            ((name_ + ".bus").c_str(),
                po::value<core::identity_seq>(&opts.predefined_buses),
                "List of predefined buses")
            ((name_ + ".allow-create").c_str(),
                po::bool_switch(&opts.allow_create)->default_value(true),
                "Allow creation of new bus objects")
            ((name_ + ".collocate-registry").c_str(),
                po::bool_switch(&opts.collocate_registry)->default_value(false),
                "Locator registry is collocated in same process")
            ((name_ + ".print-proxy").c_str(),
                po::bool_switch(&opts.print_proxy),
                "Print bus registry proxy to ::std::cout")
        ;

        po::variables_map vm;
        cnctr->configure_options(opts_desc, vm);

        if (opts.publisher_endpoints.empty())
            opts.publisher_endpoints.push_back(core::endpoint::tcp("0.0.0.0", 0));

        bus_adapter_ = cnctr->create_adapter(
                core::identity::random(opts.bus_adapter_category),
                opts.bus_endpoints);
        bus_adapter_->activate();

        publisher_adapter_ = cnctr->create_adapter(
                core::identity::random(opts.publisher_adapter_category),
                opts.publisher_endpoints);
        publisher_adapter_->activate();

        auto pub_ptr = ::std::make_shared<publisher>();
        publisher_adapter_->add_default_servant(pub_ptr);
        auto bus_ptr = ::std::make_shared<bus_impl>(publisher_adapter_, pub_ptr);
        bus_adapter_->add_default_servant(bus_ptr);
        auto reg_ptr = ::std::make_shared<registry_impl>(bus_adapter_, pub_ptr);
        auto prx = bus_adapter_->add_object(opts.bus_registry_id, reg_ptr);
        registry_ = core::unchecked_cast< bus::bus_registry_proxy >(prx);

        for (auto const& id : opts.predefined_buses) {
            pub_ptr->add_bus(id);
        }
        if (opts.print_proxy) {
            ::std::cout << *registry_ << ::std::endl;
        }
    }

    void
    stop()
    {
        publisher_adapter_->deactivate();
        bus_adapter_->deactivate();
    }
};

bus_service::bus_service(::std::string const& name)
    : pimpl_{util::make_unique<impl>(name)}
{
}

bus_service::~bus_service() = default;

void
bus_service::start(core::connector_ptr cnctr)
{
    pimpl_->start(cnctr);
}

void
bus_service::stop()
{
    pimpl_->stop();
}

bus::bus_registry_prx
bus_service::registry() const
{
    return pimpl_->registry_;
}

}  /* namespace svc */
}  /* namespace wire */

ext: cpp

max_stars_repo_name: zmij/wire

max_issues_repo_name: zmij/wire

max_forks_repo_name: zmij/wire


text:
//===- Offset.test.cpp ------------------------------------------*- C++ -*-===//
//
//  Copyright (C) 2020 GrammaTech, Inc.
//
//  This code is licensed under the MIT license. See the LICENSE file in the
//  project root for license terms.
//
//  This project is sponsored by the Office of Naval Research, One Liberty
//  Center, 875 N. Randolph Street, Arlington, VA 22203 under contract #
//  N68335-17-C-0700.  The content of the information does not necessarily
//  reflect the position or policy of the Government and no official
//  endorsement should be inferred.
//
//===----------------------------------------------------------------------===//
#include <gtirb/Offset.hpp>
#include <boost/uuid/random_generator.hpp>
#include <gtest/gtest.h>

using namespace gtirb;

TEST(Unit_Offset, ordering) {
  UUID uuid1{boost::uuids::random_generator()()};
  UUID uuid2{boost::uuids::random_generator()()};
  uint64_t disp1(5);
  uint64_t disp2(10);
  Offset offset1(uuid1, disp1);
  Offset offset2(uuid1, disp2);
  Offset offset3(uuid2, disp1);
  Offset offset4(uuid2, disp2);
  EXPECT_TRUE(offset1 < offset2);
  EXPECT_TRUE(offset3 < offset4);
  if (uuid1 < uuid2) {
    EXPECT_TRUE(offset1 < offset3);
    EXPECT_TRUE(offset2 < offset3);
    EXPECT_TRUE(offset1 < offset4);
    EXPECT_TRUE(offset2 < offset4);
  }
  if (uuid2 < uuid1) {
    EXPECT_TRUE(offset1 > offset3);
    EXPECT_TRUE(offset2 > offset3);
    EXPECT_TRUE(offset1 > offset4);
    EXPECT_TRUE(offset2 > offset4);
  }
}

TEST(Unit_Offset, hash) {
  UUID uuid1{boost::uuids::random_generator()()};
  uint64_t disp1(5);
  uint64_t disp2(10);
  Offset offset1(uuid1, disp1);
  Offset offset2(uuid1, disp2);
  EXPECT_EQ(std::hash<Offset>()(offset1), std::hash<Offset>()(offset1));
  EXPECT_NE(std::hash<Offset>()(offset1), std::hash<Offset>()(offset2));
}

max_stars_repo_name: clayne/gtirb

max_issues_repo_name: clayne/gtirb

max_forks_repo_name: clayne/gtirb


text:
/*==============================================================================
    Copyright (c) 2005, 2008 Peter Dimov
    Copyright (c) 2005-2010 Joel de Guzman
    Copyright (c) 2010 Thomas Heller

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/

#include <boost/config.hpp>

#if defined(BOOST_MSVC)
#pragma warning(disable: 4786)  // identifier truncated in debug info
#pragma warning(disable: 4710)  // function not inlined
#pragma warning(disable: 4711)  // function selected for automatic inline expansion
#pragma warning(disable: 4514)  // unreferenced inline removed
#endif

#include <boost/phoenix/core.hpp>
#include <boost/phoenix/bind.hpp>

#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
#pragma warning(push, 3)
#endif

#include <iostream>

#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
#pragma warning(pop)
#endif

#include <boost/detail/lightweight_test.hpp>

struct X
{
    mutable unsigned int hash;

    typedef int result_type;

    X(): hash(0) {}

    int operator()() const { operator()(17); return 0; }
    int operator()(int a1) const { hash = (hash * 17041 + a1 * 2) % 32768; return 0; }
    int operator()(int a1, int a2) const { operator()(a1); operator()(a2); return 0; }
    int operator()(int a1, int a2, int a3) const { operator()(a1, a2); operator()(a3); return 0; }
    int operator()(int a1, int a2, int a3, int a4) const { operator()(a1, a2, a3); operator()(a4); return 0; }
    int operator()(int a1, int a2, int a3, int a4, int a5) const { operator()(a1, a2, a3, a4); operator()(a5); return 0; }
    int operator()(int a1, int a2, int a3, int a4, int a5, int a6) const { operator()(a1, a2, a3, a4, a5); operator()(a6); return 0; }
    int operator()(int a1, int a2, int a3, int a4, int a5, int a6, int a7) const { operator()(a1, a2, a3, a4, a5, a6); operator()(a7); return 0; }
    int operator()(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) const { operator()(a1, a2, a3, a4, a5, a6, a7); operator()(a8); return 0; }
    int operator()(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9) const { operator()(a1, a2, a3, a4, a5, a6, a7, a8); operator()(a9); return 0; }
};

void function_object_test()
{
    using boost::phoenix::bind;
    using boost::phoenix::ref;

    X x;

    bind(ref(x) )();
    bind(ref(x), 1 )();
    bind(ref(x), 1, 2 )();
    bind(ref(x), 1, 2, 3 )();
    bind(ref(x), 1, 2, 3, 4 )();
    bind(ref(x), 1, 2, 3, 4, 5 )();
    bind(ref(x), 1, 2, 3, 4, 5, 6 )();
    bind(ref(x), 1, 2, 3, 4, 5, 6, 7)();
    bind(ref(x), 1, 2, 3, 4, 5, 6, 7, 8 )();
    bind(ref(x), 1, 2, 3, 4, 5, 6, 7, 8, 9 )();

    BOOST_TEST( x.hash == 9932 );
}

int main()
{
    function_object_test();
    return boost::report_errors();
}

max_stars_repo_name: randolphwong/mcsema

max_issues_repo_name: randolphwong/mcsema

max_forks_repo_name: randolphwong/mcsema


text:
#include <boost/range/adaptors.hpp>
#include <boost/range/algorithm.hpp>
#include "AdditionalEffectMessages.hpp"
#include "Creature.hpp"
#include "EffectTextKeys.hpp"
#include "MessageManager.hpp"
#include "StatusEffectFactory.hpp"
#include "TimewalkEffect.hpp"

using namespace std;

TimewalkEffect::TimewalkEffect()
{
}

string TimewalkEffect::get_effect_identification_message(CreaturePtr creature) const
{
  string effect_msg;

  if (creature)
  {
    effect_msg = EffectTextKeys::get_timewalk_effect_message(creature->get_description_sid(), creature->get_is_player());
  }

  return effect_msg;
}

Effect* TimewalkEffect::clone()
{
  return new TimewalkEffect(*this);
}

bool TimewalkEffect::effect_blessed(CreaturePtr creature, ActionManager * const am, const Coordinate& affected_coordinate, TilePtr affected_tile)
{
  return timewalk(creature);
}

bool TimewalkEffect::effect_uncursed(CreaturePtr creature, ActionManager * const am, const Coordinate& affected_coordinate, TilePtr affected_tile)
{
  return timewalk(creature);
}

bool TimewalkEffect::effect_cursed(CreaturePtr creature, ActionManager * am, const Coordinate& affected_coordinate, TilePtr affected_tile)
{
  return timewalk(creature);
}

bool TimewalkEffect::timewalk(CreaturePtr creature)
{
  bool timewalked = false;

  if (creature != nullptr)
  {
    StatusEffectPtr tw = StatusEffectFactory::create_status_effect(this->get_originator(), StatusIdentifiers::STATUS_ID_TIMEWALK, creature->get_id());
    tw->apply_change(creature, creature->get_level().get_current());

    timewalked = true;
  }

  return timewalked;
}

max_stars_repo_name: prolog/shadow-of-the-wyrm

max_issues_repo_name: prolog/shadow-of-the-wyrm

max_forks_repo_name: prolog/shadow-of-the-wyrm


text:
// Copyright (C) 2012 Vicente J. Botet Escriba
//
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
// The make_tuple_indices code is based on the one from libcxx.
//===----------------------------------------------------------------------===//

#ifndef BOOST_THREAD_DETAIL_MAKE_TUPLE_INDICES_HPP
#define BOOST_THREAD_DETAIL_MAKE_TUPLE_INDICES_HPP

#include <boost/config.hpp>
#include <boost/static_assert.hpp>

namespace boost
{
  namespace detail
  {

#if ! defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
    ! defined(BOOST_NO_CXX11_RVALUE_REFERENCES)

    // make_tuple_indices

    template <std::size_t...> struct tuple_indices
    {};

    template <std::size_t Sp, class IntTuple, std::size_t Ep>
    struct make_indices_imp;

    template <std::size_t Sp, std::size_t ...Indices, std::size_t Ep>
    struct make_indices_imp<Sp, tuple_indices<Indices...>, Ep>
    {
      typedef typename make_indices_imp<Sp+1, tuple_indices<Indices..., Sp>, Ep>::type type;
    };

    template <std::size_t Ep, std::size_t ...Indices>
    struct make_indices_imp<Ep, tuple_indices<Indices...>, Ep>
    {
      typedef tuple_indices<Indices...> type;
    };

    template <std::size_t Ep, std::size_t Sp = 0>
    struct make_tuple_indices
    {
      BOOST_STATIC_ASSERT_MSG(Sp <= Ep, "make_tuple_indices input error");
      typedef typename make_indices_imp<Sp, tuple_indices<>, Ep>::type type;
    };
#endif
  }
}

#endif // header

max_stars_repo_name: kamarianakis/glGA-edu

max_issues_repo_name: kamarianakis/glGA-edu


text:
/* Copyright (c) 2017, United States Government, as represented by the
 * Administrator of the National Aeronautics and Space Administration.
 *
 * All rights reserved.
 *
 * The Astrobee platform is 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 <interest_point/matching.h>
#include <interest_point/brisk.h>
#include <opencv2/xfeatures2d.hpp>

#include <Eigen/Core>
#include <gflags/gflags.h>
#include <glog/logging.h>

#include <iostream>
#include <vector>
// Note: if any of these values are manually set by the user in
// build_map, the localize script must be invoked with precisely the
// same settings!
// TODO(oalexan1): Ideally the settings used here must be saved in the
// map file, for the localize executable to read them from there.
DEFINE_int32(hamming_distance, 90,
             "A smaller value keeps fewer but more reliable binary descriptor matches.");
DEFINE_double(goodness_ratio, 0.8,
              "A smaller value keeps fewer but more reliable float descriptor matches.");
DEFINE_int32(surf_mode, 1,
             "0: Use default SURF, 1: use dynamic adaptive SURF, 2: Use grid adaptive SURF.");

DEFINE_int32(orgbrisk_octaves, 4,
             "Number of octaves, or scale spaces, that BRISK will evaluate.");
DEFINE_double(orgbrisk_pattern_scale, 1.0,
             "The pattern scale to use for BRISK.");

namespace interest_point {

  DynamicDetector::DynamicDetector(unsigned int min_features, unsigned int max_features, unsigned int max_retries) :
         min_features_(min_features), max_features_(max_features), max_retries_(max_retries) {}

  void DynamicDetector::Detect(const cv::Mat& image,
                               std::vector<cv::KeyPoint>* keypoints,
                               cv::Mat* keypoints_description) {
    for (unsigned int i = 0; i < max_retries_; i++) {
      keypoints->clear();
      DetectImpl(image, keypoints);
      if (keypoints->size() < min_features_)
        TooFew();
      else if (keypoints->size() > max_features_)
        TooMany();
      else
        break;
    }
    ComputeImpl(image, keypoints, keypoints_description);
  }

  class BriskDynamicDetector : public DynamicDetector {
   public:
    BriskDynamicDetector(unsigned int min_features, unsigned int max_features,
                         unsigned int max_retries)
         : DynamicDetector(min_features, max_features, max_retries), threshold_(100) {
      Reset();
    }

    void Reset(void) {
      brisk_ = interest_point::BRISK::create(threshold_, FLAGS_orgbrisk_octaves,
                                 FLAGS_orgbrisk_pattern_scale);
    }

    virtual void DetectImpl(const cv::Mat& image, std::vector<cv::KeyPoint>* keypoints) {
      brisk_->detect(image, *keypoints);
    }
    virtual void ComputeImpl(const cv::Mat& image, std::vector<cv::KeyPoint>* keypoints,
                             cv::Mat* keypoints_description) {
      brisk_->compute(image, *keypoints, *keypoints_description);
    }
    virtual void TooMany(void) {
      threshold_ *= 1.25;
      if (threshold_ > 200)
        threshold_ = 200;
      brisk_->setThreshold(threshold_);
    }
    virtual void TooFew(void) {
      threshold_ *= 0.8;
      if (threshold_ < 80)
        threshold_ = 80;
      brisk_->setThreshold(threshold_);
    }

   private:
    cv::Ptr<interest_point::BRISK> brisk_;
    unsigned int threshold_;
  };

  class SurfDynamicDetector : public DynamicDetector {
   public:
    SurfDynamicDetector(unsigned int min_features, unsigned int max_features, unsigned int max_retries, float threshold)
         : DynamicDetector(min_features, max_features, max_retries), threshold_(threshold) {
      surf_ = cv::xfeatures2d::SURF::create(threshold);
    }

    virtual void DetectImpl(const cv::Mat& image, std::vector<cv::KeyPoint>* keypoints) {
      surf_->detect(image, *keypoints);
    }
    virtual void ComputeImpl(const cv::Mat& image, std::vector<cv::KeyPoint>* keypoints,
                             cv::Mat* keypoints_description) {
      surf_->compute(image, *keypoints, *keypoints_description);
    }
    virtual void TooMany(void) {
      threshold_ *= 1.1;
      surf_->setHessianThreshold(threshold_);
    }
    virtual void TooFew(void) {
      threshold_ *= 0.9;
      if (threshold_ < 1.1)
        threshold_ = 1.1;
      surf_->setHessianThreshold(threshold_);
    }

   private:
    cv::Ptr<cv::xfeatures2d::SURF> surf_;
    float threshold_;
  };

  FeatureDetector::FeatureDetector(std::string const& detector_name,
                                   int min_features, int max_features,
                                   int retries) {
    detector_ = NULL;
    Reset(detector_name, min_features, max_features, retries);
  }

  FeatureDetector::~FeatureDetector(void) {
    if (detector_ != NULL) {
      delete detector_;
      detector_ = NULL;
    }
  }

  void FeatureDetector::Reset(std::string const& detector_name,
                              int min_features, int max_features,
                              int retries) {
    detector_name_   = detector_name;

    if (detector_ != NULL) {
      delete detector_;
      detector_ = NULL;
    }

    // Loading the detector
    if (detector_name == "ORGBRISK") {
      detector_ = new BriskDynamicDetector(min_features, max_features,
                                           retries);
    } else if (detector_name == "SURF") {
      detector_ = new SurfDynamicDetector(min_features, max_features, retries, 10.0);
    } else {
      LOG(FATAL) << "Unimplemented feature detector " << detector_name;
    }
  }

  void FeatureDetector::Detect(const cv::Mat& image,
                               std::vector<cv::KeyPoint>* keypoints,
                               cv::Mat* keypoints_description) {
    if (detector_ == NULL)
      LOG(FATAL) << "The detector was not initialized.";

    detector_->Detect(image, keypoints, keypoints_description);

    // Normalize the image points relative to the center of the image
    for (cv::KeyPoint& key : *keypoints) {
      key.pt.x -= image.cols/2.0;
      key.pt.y -= image.rows/2.0;
    }
  }

  void FindMatches(const cv::Mat & img1_descriptor_map,
                   const cv::Mat & img2_descriptor_map, std::vector<cv::DMatch> * matches) {
    CHECK(img1_descriptor_map.depth() ==
          img2_descriptor_map.depth())
      << "Mixed descriptor types. Did you mash BRISK with SIFT/SURF?";

    // Check for early exit conditions
    matches->clear();
    if (img1_descriptor_map.rows == 0 ||
        img2_descriptor_map.rows == 0)
      return;

    if (img1_descriptor_map.depth() == CV_8U) {
      // Binary descriptor

      // cv::BFMatcher matcher(cv::NORM_HAMMING, true  /* Forward & Backward matching */);
      cv::FlannBasedMatcher matcher(cv::makePtr<cv::flann::LshIndexParams>(3, 18, 2));
      matcher.match(img1_descriptor_map, img2_descriptor_map, *matches);

      // Select only inlier matches that meet a BRISK threshold of
      // of FLAGS_hamming_distance.
      // TODO(oalexan1) This needs further study.
      std::vector<cv::DMatch> inlier_matches;
      inlier_matches.reserve(matches->size());  // This saves time in allocation
      for (cv::DMatch const& dmatch : *matches) {
        if (dmatch.distance < FLAGS_hamming_distance) {
          inlier_matches.push_back(dmatch);
        }
      }
      matches->swap(inlier_matches);  // Doesn't invoke a copy of all elements.
    } else {
      // Traditional floating point descriptor
      cv::FlannBasedMatcher matcher;
      std::vector<std::vector<cv::DMatch> > possible_matches;
      matcher.knnMatch(img1_descriptor_map, img2_descriptor_map, possible_matches, 2);
      matches->clear();
      matches->reserve(possible_matches.size());
      for (std::vector<cv::DMatch> const& best_pair : possible_matches) {
        if (best_pair.size() == 1) {
          // This was the only best match, push it.
          matches->push_back(best_pair.at(0));
        } else {
          // Push back a match only if it is 25% better than the next best.
          if (best_pair.at(0).distance < FLAGS_goodness_ratio * best_pair.at(1).distance) {
            matches->push_back(best_pair[0]);
          }
        }
      }
    }
  }
}  // namespace interest_point

ext: cc

max_stars_repo_name: algprasad/astrobee

max_issues_repo_name: Giovan/astrobee

max_forks_repo_name: Giovan/astrobee


text:
#include "HttpWorkerThread.h"
#include "HttpRequest.h"
#include "strutil.h"
#include <sstream>
#include <iostream>
#include <boost/filesystem.hpp>

using std::chrono::duration_cast;
using std::chrono::steady_clock;
using boost::filesystem::exists;
using boost::filesystem::last_write_time;
using boost::filesystem::path;
using boost::filesystem::file_size;
using boost::filesystem::load_string_file;
using boost::filesystem::save_string_file;

HttpWorkerThread::HttpWorkerThread(int socket_fd, std::string &http_version, int timeout) {
    std::cout << "Started new worker for socket: " << socket_fd << std::endl;
    done = false;
    this->socket = new Socket(socket_fd);
    this->timeout = timeout;
    this->http_version = http_version;
    start();
}

HttpWorkerThread::~HttpWorkerThread(){
    std::cout << "A worker just terminated" << std::endl;
    if (worker != nullptr) {
        worker->join();
    }
    delete worker;
    if (socket != nullptr) {
        socket->close();
    }
    delete socket;
}

bool HttpWorkerThread::is_done() {
    return done;
}

void HttpWorkerThread::start() {
    start_time = steady_clock::now();
    worker = new std::thread(&HttpWorkerThread::execute, this);
}

void HttpWorkerThread::execute() {
    while (!done) {
        std::string headers = socket->receive_http_msg_headers(false);
        if (!headers.empty()) {
            std::cout << "\n\nHeaders of Received Request\n" << headers << "\n\n";
            handle_http_request(headers);
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(30));
        auto now = steady_clock::now();
        int64_t time_diff = duration_cast<std::chrono::seconds>(now - start_time).count();
        if (time_diff >= timeout) {
            done = true;
        }
    }
    std::cout << "A worker just timed out" << std::endl;
}

void HttpWorkerThread::handle_http_request(std::string &http_request) {
    HttpRequest request(http_request);
    std::stringstream response_stream;
    std::string file_name = "." + request.get_file_url();
    path file_path = path(file_name);
    std::string response_code = "200 OK";

    if (request.get_request_method() == GET) {
        if (!exists(file_path)) {
            response_stream << http_version << ' ' << "404 Not Found" << "\r\n\r\n";
            std::string response = response_stream.str();
            socket->send_http_msg(response);
            return;
        }
        response_stream << http_version << ' ' << response_code << "\r\n";
        time_t now;
        time(&now);
        response_stream << "Date: " << strutil::time_cstr(&now) << "\r\n";
        response_stream << "Server: " << "Dummy" << "\r\n";
        time_t last_modified = last_write_time(file_path);
        response_stream << "Last-Modified: " << strutil::time_cstr(&last_modified) << "\r\n";
        response_stream << "Content-Length: " << file_size(file_path) << "\r\n";
        response_stream << "Content-Type: " << get_content_type(file_name) << "\r\n";
        response_stream << "\r\n";
        std::string response = response_stream.str();
        socket->send_http_msg(response);

        std::string data;
        load_string_file(file_path, data);
        socket->send_http_msg(data);

    } else if (request.get_request_method() == POST) {
        std::string length_str = request.get_options()["Content-Length"];
        int length = atoi(length_str.c_str());
        if (length <= 0) {
            response_stream << http_version << ' ' << "400 Bad Request" << "\r\n\r\n";
            std::string response = response_stream.str();
            socket->send_http_msg(response);
            std::cout << "Sent Response:\n" << response << std::endl;

            return;
        } else {
            response_stream << http_version << ' ' << response_code << "\r\n\r\n";
            std::string response = response_stream.str();
            socket->send_http_msg(response);

            std::cout << "Sent Response:\n" << response << std::endl;

            std::string body = socket->receive_http_msg_body(length);
            save_string_file(file_path, body);
        }
    }
}

std::string HttpWorkerThread::get_content_type(std::string url) {
	std::string contentType;
    std::string extension = url.substr(url.find_last_of(".") + 1);

	if (strutil::iequals(extension, "html")) {
		contentType = "text/html";
	} else if (strutil::iequals(extension, "txt")) {
		contentType = "text/txt";
	} else if (strutil::iequals(extension, "css")) {
		contentType = "text/css";
	} else if (strutil::iequals(extension, "js")) {
		contentType = "text/javascript";
	}else if (strutil::iequals(extension, "png")) {
		contentType = "image/png";
	} else if (strutil::iequals(extension, "jpg")) {
		contentType = "image/jpg";
	} else if (strutil::iequals(extension, "jpeg")) {
		contentType = "image/jpg";
	} else if (strutil::iequals(extension, "gif")) {
		contentType = "image/gif";
	} else {
		contentType = "text/txt";
	}
	return contentType;
}

max_stars_repo_name: MohamedAshrafTolba/http-client-server

max_issues_repo_name: MohamedAshrafTolba/http-client-server

max_forks_repo_name: MohamedAshrafTolba/http-client-server