<commit_before>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2015-2017 Baldur Karlsson
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/

#include "vk_state.h"
#include "vk_core.h"
#include "vk_info.h"
#include "vk_resources.h"

VulkanRenderState::VulkanRenderState(WrappedVulkan *driver, VulkanCreationInfo *createInfo)
    : m_CreationInfo(createInfo), m_pDriver(driver)
{
  compute.pipeline = graphics.pipeline = renderPass = framebuffer = ResourceId();
  compute.descSets.clear();
  graphics.descSets.clear();

  views.clear();
  scissors.clear();
  lineWidth = 1.0f;
  RDCEraseEl(bias);
  RDCEraseEl(blendConst);
  mindepth = 0.0f;
  maxdepth = 1.0f;
  RDCEraseEl(front);
  RDCEraseEl(back);
  RDCEraseEl(pushconsts);

  renderPass = ResourceId();
  subpass = 0;

  RDCEraseEl(renderArea);

  RDCEraseEl(ibuffer);
  vbuffers.clear();
}

VulkanRenderState &VulkanRenderState::operator=(const VulkanRenderState &o)
{
  views = o.views;
  scissors = o.scissors;
  lineWidth = o.lineWidth;
  bias = o.bias;
  memcpy(blendConst, o.blendConst, sizeof(blendConst));
  mindepth = o.mindepth;
  maxdepth = o.maxdepth;
  front = o.front;
  back = o.back;
  memcpy(pushconsts, o.pushconsts, sizeof(pushconsts));
  renderPass = o.renderPass;
  subpass = o.subpass;
  framebuffer = o.framebuffer;
  renderArea = o.renderArea;

  compute.pipeline = o.compute.pipeline;
  compute.descSets = o.compute.descSets;

  graphics.pipeline = o.graphics.pipeline;
  graphics.descSets = o.graphics.descSets;

  ibuffer = o.ibuffer;
  vbuffers = o.vbuffers;

  return *this;
}

void VulkanRenderState::BeginRenderPassAndApplyState(VkCommandBuffer cmd, PipelineBinding binding)
{
  RDCASSERT(renderPass != ResourceId());

  // clear values don't matter as we're using the load renderpass here, that
  // has all load ops set to load (as we're doing a partial replay - can't
  // just clear the targets that are partially written to).

  VkClearValue empty[16] = {};

  RDCASSERT(ARRAY_COUNT(empty) >= m_CreationInfo->m_RenderPass[renderPass].attachments.size());

  VkRenderPassBeginInfo rpbegin = {
      VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
      NULL,
      Unwrap(m_CreationInfo->m_RenderPass[renderPass].loadRPs[subpass]),
      Unwrap(GetResourceManager()->GetCurrentHandle<VkFramebuffer>(framebuffer)),
      renderArea,
      (uint32_t)m_CreationInfo->m_RenderPass[renderPass].attachments.size(),
      empty,
  };
  ObjDisp(cmd)->CmdBeginRenderPass(Unwrap(cmd), &rpbegin, VK_SUBPASS_CONTENTS_INLINE);

  BindPipeline(cmd, binding, true);

  if(ibuffer.buf != ResourceId())
    ObjDisp(cmd)->CmdBindIndexBuffer(
        Unwrap(cmd), Unwrap(GetResourceManager()->GetCurrentHandle<VkBuffer>(ibuffer.buf)),
        ibuffer.offs, ibuffer.bytewidth == 4 ? VK_INDEX_TYPE_UINT32 : VK_INDEX_TYPE_UINT16);

  for(size_t i = 0; i < vbuffers.size(); i++)
    ObjDisp(cmd)->CmdBindVertexBuffers(
        Unwrap(cmd), (uint32_t)i, 1,
        UnwrapPtr(GetResourceManager()->GetCurrentHandle<VkBuffer>(vbuffers[i].buf)),
        &vbuffers[i].offs);
}

void VulkanRenderState::BindPipeline(VkCommandBuffer cmd, PipelineBinding binding, bool subpass0)
{
  if(graphics.pipeline != ResourceId() && binding == BindGraphics)
  {
    VkPipeline pipe = GetResourceManager()->GetCurrentHandle<VkPipeline>(graphics.pipeline);

    if(subpass0 && m_CreationInfo->m_Pipeline[graphics.pipeline].subpass0pipe != VK_NULL_HANDLE)
      pipe = m_CreationInfo->m_Pipeline[graphics.pipeline].subpass0pipe;

    ObjDisp(cmd)->CmdBindPipeline(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS, Unwrap(pipe));

    ResourceId pipeLayoutId = m_CreationInfo->m_Pipeline[graphics.pipeline].layout;
    VkPipelineLayout layout = GetResourceManager()->GetCurrentHandle<VkPipelineLayout>(pipeLayoutId);

    const vector<VkPushConstantRange> &pushRanges =
        m_CreationInfo->m_PipelineLayout[pipeLayoutId].pushRanges;

    bool dynamicStates[VK_DYNAMIC_STATE_RANGE_SIZE] = {0};
    memcpy(dynamicStates, m_CreationInfo->m_Pipeline[graphics.pipeline].dynamicStates,
           sizeof(dynamicStates));

    RDCCOMPILE_ASSERT(sizeof(dynamicStates) ==
                          sizeof(m_CreationInfo->m_Pipeline[graphics.pipeline].dynamicStates),
                      "Dynamic states array size is out of sync");

    if(!views.empty() && dynamicStates[VK_DYNAMIC_STATE_VIEWPORT])
      ObjDisp(cmd)->CmdSetViewport(Unwrap(cmd), 0, (uint32_t)views.size(), &views[0]);
    if(!scissors.empty() && dynamicStates[VK_DYNAMIC_STATE_SCISSOR])
      ObjDisp(cmd)->CmdSetScissor(Unwrap(cmd), 0, (uint32_t)scissors.size(), &scissors[0]);

    if(dynamicStates[VK_DYNAMIC_STATE_LINE_WIDTH])
      ObjDisp(cmd)->CmdSetLineWidth(Unwrap(cmd), lineWidth);

    if(dynamicStates[VK_DYNAMIC_STATE_DEPTH_BIAS])
      ObjDisp(cmd)->CmdSetDepthBias(Unwrap(cmd), bias.depth, bias.biasclamp, bias.slope);

    if(dynamicStates[VK_DYNAMIC_STATE_BLEND_CONSTANTS])
      ObjDisp(cmd)->CmdSetBlendConstants(Unwrap(cmd), blendConst);

    if(dynamicStates[VK_DYNAMIC_STATE_DEPTH_BOUNDS])
      ObjDisp(cmd)->CmdSetDepthBounds(Unwrap(cmd), mindepth, maxdepth);

    if(dynamicStates[VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK])
    {
      ObjDisp(cmd)->CmdSetStencilCompareMask(Unwrap(cmd), VK_STENCIL_FACE_BACK_BIT, back.compare);
      ObjDisp(cmd)->CmdSetStencilCompareMask(Unwrap(cmd), VK_STENCIL_FACE_FRONT_BIT, front.compare);
    }

    if(dynamicStates[VK_DYNAMIC_STATE_STENCIL_WRITE_MASK])
    {
      ObjDisp(cmd)->CmdSetStencilWriteMask(Unwrap(cmd), VK_STENCIL_FACE_BACK_BIT, back.write);
      ObjDisp(cmd)->CmdSetStencilWriteMask(Unwrap(cmd), VK_STENCIL_FACE_FRONT_BIT, front.write);
    }

    if(dynamicStates[VK_DYNAMIC_STATE_STENCIL_REFERENCE])
    {
      ObjDisp(cmd)->CmdSetStencilReference(Unwrap(cmd), VK_STENCIL_FACE_BACK_BIT, back.ref);
      ObjDisp(cmd)->CmdSetStencilReference(Unwrap(cmd), VK_STENCIL_FACE_FRONT_BIT, front.ref);
    }

    // only set push constant ranges that the layout uses
    for(size_t i = 0; i < pushRanges.size(); i++)
      ObjDisp(cmd)->CmdPushConstants(Unwrap(cmd), Unwrap(layout), pushRanges[i].stageFlags,
                                     pushRanges[i].offset, pushRanges[i].size,
                                     pushconsts + pushRanges[i].offset);

    const vector<ResourceId> &descSetLayouts =
        m_CreationInfo->m_PipelineLayout[pipeLayoutId].descSetLayouts;

    // only iterate over the desc sets that this layout actually uses, not all that were bound
    for(size_t i = 0; i < descSetLayouts.size(); i++)
    {
      const DescSetLayout &descLayout = m_CreationInfo->m_DescSetLayout[descSetLayouts[i]];

      if(i < graphics.descSets.size() && graphics.descSets[i].descSet != ResourceId())
      {
        // if we come to a descriptor set that isn't compatible, stop setting descriptor sets from
        // here on.
        // We can get into this situation if for example we have many sets bound at some point, then
        // there's a pipeline change that causes most or all of them to be invalidated as
        // incompatible, then the program only re-binds some subset that it knows is statically used
        // by the next drawcall. The remaining sets are invalid, but also unused and this is
        // explicitly allowed by the spec. We just have to make sure we don't try to actively bind
        // an incompatible descriptor set.
        ResourceId createdDescSetLayoutId =
            m_pDriver->GetDescLayoutForDescSet(graphics.descSets[i].descSet);

        if(descSetLayouts[i] != createdDescSetLayoutId)
        {
          const DescSetLayout &createdDescLayout =
              m_CreationInfo->m_DescSetLayout[createdDescSetLayoutId];

          if(descLayout != createdDescLayout)
            break;
        }

        // if there are dynamic buffers, pass along the offsets

        uint32_t *dynamicOffsets = NULL;

        if(descLayout.dynamicCount > 0)
        {
          dynamicOffsets = &graphics.descSets[i].offsets[0];

          if(graphics.descSets[i].offsets.size() < descLayout.dynamicCount)
          {
            dynamicOffsets = new uint32_t[descLayout.dynamicCount];
            for(uint32_t o = 0; o < descLayout.dynamicCount; o++)
            {
              if(o < graphics.descSets[i].offsets.size())
              {
                dynamicOffsets[o] = graphics.descSets[i].offsets[o];
              }
              else
              {
                dynamicOffsets[o] = 0;
                RDCWARN("Missing dynamic offset for set %u!", (uint32_t)i);
              }
            }
          }
        }

        ObjDisp(cmd)->CmdBindDescriptorSets(
            Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS, Unwrap(layout), (uint32_t)i, 1,
            UnwrapPtr(GetResourceManager()->GetCurrentHandle<VkDescriptorSet>(
                graphics.descSets[i].descSet)),
            descLayout.dynamicCount, dynamicOffsets);

        if(graphics.descSets[i].offsets.size() < descLayout.dynamicCount)
          SAFE_DELETE_ARRAY(dynamicOffsets);
      }
      else
      {
        RDCWARN("Descriptor set is not bound but pipeline layout expects one");
      }
    }
  }

  if(compute.pipeline != ResourceId() && binding == BindCompute)
  {
    ObjDisp(cmd)->CmdBindPipeline(
        Unwrap(cmd), VK_PIPELINE_BIND_POINT_COMPUTE,
        Unwrap(GetResourceManager()->GetCurrentHandle<VkPipeline>(compute.pipeline)));

    ResourceId pipeLayoutId = m_CreationInfo->m_Pipeline[compute.pipeline].layout;
    VkPipelineLayout layout = GetResourceManager()->GetCurrentHandle<VkPipelineLayout>(pipeLayoutId);

    const vector<VkPushConstantRange> &pushRanges =
        m_CreationInfo->m_PipelineLayout[pipeLayoutId].pushRanges;

    // only set push constant ranges that the layout uses
    for(size_t i = 0; i < pushRanges.size(); i++)
      ObjDisp(cmd)->CmdPushConstants(Unwrap(cmd), Unwrap(layout), pushRanges[i].stageFlags,
                                     pushRanges[i].offset, pushRanges[i].size,
                                     pushconsts + pushRanges[i].offset);

    const vector<ResourceId> &descSetLayouts =
        m_CreationInfo->m_PipelineLayout[pipeLayoutId].descSetLayouts;

    for(size_t i = 0; i < descSetLayouts.size(); i++)
    {
      const DescSetLayout &descLayout = m_CreationInfo->m_DescSetLayout[descSetLayouts[i]];

      if(i < compute.descSets.size() && compute.descSets[i].descSet != ResourceId())
      {
        // if there are dynamic buffers, pass along the offsets

        uint32_t *dynamicOffsets = NULL;

        if(descLayout.dynamicCount > 0)
        {
          dynamicOffsets = &compute.descSets[i].offsets[0];

          if(compute.descSets[i].offsets.size() < descLayout.dynamicCount)
          {
            dynamicOffsets = new uint32_t[descLayout.dynamicCount];
            for(uint32_t o = 0; o < descLayout.dynamicCount; o++)
            {
              if(o < compute.descSets[i].offsets.size())
              {
                dynamicOffsets[o] = compute.descSets[i].offsets[o];
              }
              else
              {
                dynamicOffsets[o] = 0;
                RDCWARN("Missing dynamic offset for set %u!", (uint32_t)i);
              }
            }
          }
        }

        ObjDisp(cmd)->CmdBindDescriptorSets(
            Unwrap(cmd), VK_PIPELINE_BIND_POINT_COMPUTE, Unwrap(layout), (uint32_t)i, 1,
            UnwrapPtr(GetResourceManager()->GetCurrentHandle<VkDescriptorSet>(
                compute.descSets[i].descSet)),
            descLayout.dynamicCount, dynamicOffsets);

        if(compute.descSets[i].offsets.size() < descLayout.dynamicCount)
          SAFE_DELETE_ARRAY(dynamicOffsets);
      }
    }
  }
}

void VulkanRenderState::EndRenderPass(VkCommandBuffer cmd)
{
  ObjDisp(cmd)->CmdEndRenderPass(Unwrap(cmd));
}

VulkanResourceManager *VulkanRenderState::GetResourceManager()
{
  return m_pDriver->GetResourceManager();
}
<commit_msg>Bind all compatible descriptor sets, don't bail at the first one<commit_after>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2015-2017 Baldur Karlsson
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/

#include "vk_state.h"
#include "vk_core.h"
#include "vk_info.h"
#include "vk_resources.h"

VulkanRenderState::VulkanRenderState(WrappedVulkan *driver, VulkanCreationInfo *createInfo)
    : m_CreationInfo(createInfo), m_pDriver(driver)
{
  compute.pipeline = graphics.pipeline = renderPass = framebuffer = ResourceId();
  compute.descSets.clear();
  graphics.descSets.clear();

  views.clear();
  scissors.clear();
  lineWidth = 1.0f;
  RDCEraseEl(bias);
  RDCEraseEl(blendConst);
  mindepth = 0.0f;
  maxdepth = 1.0f;
  RDCEraseEl(front);
  RDCEraseEl(back);
  RDCEraseEl(pushconsts);

  renderPass = ResourceId();
  subpass = 0;

  RDCEraseEl(renderArea);

  RDCEraseEl(ibuffer);
  vbuffers.clear();
}

VulkanRenderState &VulkanRenderState::operator=(const VulkanRenderState &o)
{
  views = o.views;
  scissors = o.scissors;
  lineWidth = o.lineWidth;
  bias = o.bias;
  memcpy(blendConst, o.blendConst, sizeof(blendConst));
  mindepth = o.mindepth;
  maxdepth = o.maxdepth;
  front = o.front;
  back = o.back;
  memcpy(pushconsts, o.pushconsts, sizeof(pushconsts));
  renderPass = o.renderPass;
  subpass = o.subpass;
  framebuffer = o.framebuffer;
  renderArea = o.renderArea;

  compute.pipeline = o.compute.pipeline;
  compute.descSets = o.compute.descSets;

  graphics.pipeline = o.graphics.pipeline;
  graphics.descSets = o.graphics.descSets;

  ibuffer = o.ibuffer;
  vbuffers = o.vbuffers;

  return *this;
}

void VulkanRenderState::BeginRenderPassAndApplyState(VkCommandBuffer cmd, PipelineBinding binding)
{
  RDCASSERT(renderPass != ResourceId());

  // clear values don't matter as we're using the load renderpass here, that
  // has all load ops set to load (as we're doing a partial replay - can't
  // just clear the targets that are partially written to).

  VkClearValue empty[16] = {};

  RDCASSERT(ARRAY_COUNT(empty) >= m_CreationInfo->m_RenderPass[renderPass].attachments.size());

  VkRenderPassBeginInfo rpbegin = {
      VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
      NULL,
      Unwrap(m_CreationInfo->m_RenderPass[renderPass].loadRPs[subpass]),
      Unwrap(GetResourceManager()->GetCurrentHandle<VkFramebuffer>(framebuffer)),
      renderArea,
      (uint32_t)m_CreationInfo->m_RenderPass[renderPass].attachments.size(),
      empty,
  };
  ObjDisp(cmd)->CmdBeginRenderPass(Unwrap(cmd), &rpbegin, VK_SUBPASS_CONTENTS_INLINE);

  BindPipeline(cmd, binding, true);

  if(ibuffer.buf != ResourceId())
    ObjDisp(cmd)->CmdBindIndexBuffer(
        Unwrap(cmd), Unwrap(GetResourceManager()->GetCurrentHandle<VkBuffer>(ibuffer.buf)),
        ibuffer.offs, ibuffer.bytewidth == 4 ? VK_INDEX_TYPE_UINT32 : VK_INDEX_TYPE_UINT16);

  for(size_t i = 0; i < vbuffers.size(); i++)
    ObjDisp(cmd)->CmdBindVertexBuffers(
        Unwrap(cmd), (uint32_t)i, 1,
        UnwrapPtr(GetResourceManager()->GetCurrentHandle<VkBuffer>(vbuffers[i].buf)),
        &vbuffers[i].offs);
}

void VulkanRenderState::BindPipeline(VkCommandBuffer cmd, PipelineBinding binding, bool subpass0)
{
  if(graphics.pipeline != ResourceId() && binding == BindGraphics)
  {
    VkPipeline pipe = GetResourceManager()->GetCurrentHandle<VkPipeline>(graphics.pipeline);

    if(subpass0 && m_CreationInfo->m_Pipeline[graphics.pipeline].subpass0pipe != VK_NULL_HANDLE)
      pipe = m_CreationInfo->m_Pipeline[graphics.pipeline].subpass0pipe;

    ObjDisp(cmd)->CmdBindPipeline(Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS, Unwrap(pipe));

    ResourceId pipeLayoutId = m_CreationInfo->m_Pipeline[graphics.pipeline].layout;
    VkPipelineLayout layout = GetResourceManager()->GetCurrentHandle<VkPipelineLayout>(pipeLayoutId);

    const vector<VkPushConstantRange> &pushRanges =
        m_CreationInfo->m_PipelineLayout[pipeLayoutId].pushRanges;

    bool dynamicStates[VK_DYNAMIC_STATE_RANGE_SIZE] = {0};
    memcpy(dynamicStates, m_CreationInfo->m_Pipeline[graphics.pipeline].dynamicStates,
           sizeof(dynamicStates));

    RDCCOMPILE_ASSERT(sizeof(dynamicStates) ==
                          sizeof(m_CreationInfo->m_Pipeline[graphics.pipeline].dynamicStates),
                      "Dynamic states array size is out of sync");

    if(!views.empty() && dynamicStates[VK_DYNAMIC_STATE_VIEWPORT])
      ObjDisp(cmd)->CmdSetViewport(Unwrap(cmd), 0, (uint32_t)views.size(), &views[0]);
    if(!scissors.empty() && dynamicStates[VK_DYNAMIC_STATE_SCISSOR])
      ObjDisp(cmd)->CmdSetScissor(Unwrap(cmd), 0, (uint32_t)scissors.size(), &scissors[0]);

    if(dynamicStates[VK_DYNAMIC_STATE_LINE_WIDTH])
      ObjDisp(cmd)->CmdSetLineWidth(Unwrap(cmd), lineWidth);

    if(dynamicStates[VK_DYNAMIC_STATE_DEPTH_BIAS])
      ObjDisp(cmd)->CmdSetDepthBias(Unwrap(cmd), bias.depth, bias.biasclamp, bias.slope);

    if(dynamicStates[VK_DYNAMIC_STATE_BLEND_CONSTANTS])
      ObjDisp(cmd)->CmdSetBlendConstants(Unwrap(cmd), blendConst);

    if(dynamicStates[VK_DYNAMIC_STATE_DEPTH_BOUNDS])
      ObjDisp(cmd)->CmdSetDepthBounds(Unwrap(cmd), mindepth, maxdepth);

    if(dynamicStates[VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK])
    {
      ObjDisp(cmd)->CmdSetStencilCompareMask(Unwrap(cmd), VK_STENCIL_FACE_BACK_BIT, back.compare);
      ObjDisp(cmd)->CmdSetStencilCompareMask(Unwrap(cmd), VK_STENCIL_FACE_FRONT_BIT, front.compare);
    }

    if(dynamicStates[VK_DYNAMIC_STATE_STENCIL_WRITE_MASK])
    {
      ObjDisp(cmd)->CmdSetStencilWriteMask(Unwrap(cmd), VK_STENCIL_FACE_BACK_BIT, back.write);
      ObjDisp(cmd)->CmdSetStencilWriteMask(Unwrap(cmd), VK_STENCIL_FACE_FRONT_BIT, front.write);
    }

    if(dynamicStates[VK_DYNAMIC_STATE_STENCIL_REFERENCE])
    {
      ObjDisp(cmd)->CmdSetStencilReference(Unwrap(cmd), VK_STENCIL_FACE_BACK_BIT, back.ref);
      ObjDisp(cmd)->CmdSetStencilReference(Unwrap(cmd), VK_STENCIL_FACE_FRONT_BIT, front.ref);
    }

    // only set push constant ranges that the layout uses
    for(size_t i = 0; i < pushRanges.size(); i++)
      ObjDisp(cmd)->CmdPushConstants(Unwrap(cmd), Unwrap(layout), pushRanges[i].stageFlags,
                                     pushRanges[i].offset, pushRanges[i].size,
                                     pushconsts + pushRanges[i].offset);

    const vector<ResourceId> &descSetLayouts =
        m_CreationInfo->m_PipelineLayout[pipeLayoutId].descSetLayouts;

    // only iterate over the desc sets that this layout actually uses, not all that were bound
    for(size_t i = 0; i < descSetLayouts.size(); i++)
    {
      const DescSetLayout &descLayout = m_CreationInfo->m_DescSetLayout[descSetLayouts[i]];

      if(i < graphics.descSets.size() && graphics.descSets[i].descSet != ResourceId())
      {
        // if we come to a descriptor set that isn't compatible, stop setting descriptor sets from
        // here on.
        // We can get into this situation if for example we have many sets bound at some point, then
        // there's a pipeline change that causes most or all of them to be invalidated as
        // incompatible, then the program only re-binds some subset that it knows is statically used
        // by the next drawcall. The remaining sets are invalid, but also unused and this is
        // explicitly allowed by the spec. We just have to make sure we don't try to actively bind
        // an incompatible descriptor set.
        ResourceId createdDescSetLayoutId =
            m_pDriver->GetDescLayoutForDescSet(graphics.descSets[i].descSet);

        if(descSetLayouts[i] != createdDescSetLayoutId)
        {
          const DescSetLayout &createdDescLayout =
              m_CreationInfo->m_DescSetLayout[createdDescSetLayoutId];

          if(descLayout != createdDescLayout)
          {
            // this set is incompatible, don't rebind it. Assume the application knows the shader
            // doesn't need this set, and the binding is just stale
            continue;
          }
        }

        // if there are dynamic buffers, pass along the offsets

        uint32_t *dynamicOffsets = NULL;

        if(descLayout.dynamicCount > 0)
        {
          dynamicOffsets = &graphics.descSets[i].offsets[0];

          if(graphics.descSets[i].offsets.size() < descLayout.dynamicCount)
          {
            dynamicOffsets = new uint32_t[descLayout.dynamicCount];
            for(uint32_t o = 0; o < descLayout.dynamicCount; o++)
            {
              if(o < graphics.descSets[i].offsets.size())
              {
                dynamicOffsets[o] = graphics.descSets[i].offsets[o];
              }
              else
              {
                dynamicOffsets[o] = 0;
                RDCWARN("Missing dynamic offset for set %u!", (uint32_t)i);
              }
            }
          }
        }

        ObjDisp(cmd)->CmdBindDescriptorSets(
            Unwrap(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS, Unwrap(layout), (uint32_t)i, 1,
            UnwrapPtr(GetResourceManager()->GetCurrentHandle<VkDescriptorSet>(
                graphics.descSets[i].descSet)),
            descLayout.dynamicCount, dynamicOffsets);

        if(graphics.descSets[i].offsets.size() < descLayout.dynamicCount)
          SAFE_DELETE_ARRAY(dynamicOffsets);
      }
      else
      {
        RDCWARN("Descriptor set is not bound but pipeline layout expects one");
      }
    }
  }

  if(compute.pipeline != ResourceId() && binding == BindCompute)
  {
    ObjDisp(cmd)->CmdBindPipeline(
        Unwrap(cmd), VK_PIPELINE_BIND_POINT_COMPUTE,
        Unwrap(GetResourceManager()->GetCurrentHandle<VkPipeline>(compute.pipeline)));

    ResourceId pipeLayoutId = m_CreationInfo->m_Pipeline[compute.pipeline].layout;
    VkPipelineLayout layout = GetResourceManager()->GetCurrentHandle<VkPipelineLayout>(pipeLayoutId);

    const vector<VkPushConstantRange> &pushRanges =
        m_CreationInfo->m_PipelineLayout[pipeLayoutId].pushRanges;

    // only set push constant ranges that the layout uses
    for(size_t i = 0; i < pushRanges.size(); i++)
      ObjDisp(cmd)->CmdPushConstants(Unwrap(cmd), Unwrap(layout), pushRanges[i].stageFlags,
                                     pushRanges[i].offset, pushRanges[i].size,
                                     pushconsts + pushRanges[i].offset);

    const vector<ResourceId> &descSetLayouts =
        m_CreationInfo->m_PipelineLayout[pipeLayoutId].descSetLayouts;

    for(size_t i = 0; i < descSetLayouts.size(); i++)
    {
      const DescSetLayout &descLayout = m_CreationInfo->m_DescSetLayout[descSetLayouts[i]];

      if(i < compute.descSets.size() && compute.descSets[i].descSet != ResourceId())
      {
        // if there are dynamic buffers, pass along the offsets

        uint32_t *dynamicOffsets = NULL;

        if(descLayout.dynamicCount > 0)
        {
          dynamicOffsets = &compute.descSets[i].offsets[0];

          if(compute.descSets[i].offsets.size() < descLayout.dynamicCount)
          {
            dynamicOffsets = new uint32_t[descLayout.dynamicCount];
            for(uint32_t o = 0; o < descLayout.dynamicCount; o++)
            {
              if(o < compute.descSets[i].offsets.size())
              {
                dynamicOffsets[o] = compute.descSets[i].offsets[o];
              }
              else
              {
                dynamicOffsets[o] = 0;
                RDCWARN("Missing dynamic offset for set %u!", (uint32_t)i);
              }
            }
          }
        }

        ObjDisp(cmd)->CmdBindDescriptorSets(
            Unwrap(cmd), VK_PIPELINE_BIND_POINT_COMPUTE, Unwrap(layout), (uint32_t)i, 1,
            UnwrapPtr(GetResourceManager()->GetCurrentHandle<VkDescriptorSet>(
                compute.descSets[i].descSet)),
            descLayout.dynamicCount, dynamicOffsets);

        if(compute.descSets[i].offsets.size() < descLayout.dynamicCount)
          SAFE_DELETE_ARRAY(dynamicOffsets);
      }
    }
  }
}

void VulkanRenderState::EndRenderPass(VkCommandBuffer cmd)
{
  ObjDisp(cmd)->CmdEndRenderPass(Unwrap(cmd));
}

VulkanResourceManager *VulkanRenderState::GetResourceManager()
{
  return m_pDriver->GetResourceManager();
}
<|endoftext|>


<commit_before># include "rrdb.server.impl.h"
# include <boost/filesystem.hpp>

namespace dsn {
    namespace apps {
        rrdb_service_impl::rrdb_service_impl(::dsn::replication::replica* replica, ::dsn::configuration_ptr& config)
            : rrdb_service(replica, config)
        {
            _is_open = false;

            //
            // disable write ahead logging as replication handles logging instead now
            //
            _wt_opts.disableWAL = true;
        }

        void rrdb_service_impl::on_put(const update_request& update, ::dsn::service::rpc_replier<int>& reply)
        {
            if (_is_open)
            {
                rocksdb::WriteOptions opts = _wt_opts;
                opts.given_sequence_number = static_cast<rocksdb::SequenceNumber>(_last_committed_decree + 1);

                rocksdb::Slice skey(update.key.data(), update.key.length());
                rocksdb::Slice svalue(update.value.data(), update.value.length());
                rocksdb::Status status = _db->Put(opts, skey, svalue);
                reply(status.code());
            }
            else
            {
                reply(ERR_SERVICE_NOT_ACTIVE);
            }
        }

        void rrdb_service_impl::on_remove(const ::dsn::blob& key, ::dsn::service::rpc_replier<int>& reply)
        {
            if (_is_open)
            {
                rocksdb::WriteOptions opts = _wt_opts;
                opts.given_sequence_number = static_cast<rocksdb::SequenceNumber>(_last_committed_decree + 1);

                rocksdb::Slice skey(key.data(), key.length());
                rocksdb::Status status = _db->Delete(opts, skey);
                reply(status.code());
            }
            else
            {
                reply(ERR_SERVICE_NOT_ACTIVE);
            }
        }

        void rrdb_service_impl::on_merge(const update_request& update, ::dsn::service::rpc_replier<int>& reply)
        {
            if (_is_open)
            {
                rocksdb::WriteOptions opts = _wt_opts;
                opts.given_sequence_number = static_cast<rocksdb::SequenceNumber>(_last_committed_decree + 1);

                rocksdb::Slice skey(update.key.data(), update.key.length());
                rocksdb::Slice svalue(update.value.data(), update.value.length());
                rocksdb::Status status = _db->Merge(opts, skey, svalue);
                reply(status.code());
            }
            else
            {
                reply(ERR_SERVICE_NOT_ACTIVE);
            }
        }

        void rrdb_service_impl::on_get(const ::dsn::blob& key, ::dsn::service::rpc_replier<read_response>& reply)
        {
            read_response resp;

            if (_is_open)
            {
                rocksdb::Slice skey(key.data(), key.length());
                rocksdb::Status status = _db->Get(_rd_opts, skey, &resp.value);
                resp.error = status.code();
            }
            else
            {
                resp.error = ERR_SERVICE_NOT_ACTIVE;
            }
            reply(resp);
        }

        int  rrdb_service_impl::open(bool create_new)
        {
            if (_is_open)
                return ERR_SERVICE_ALREADY_RUNNING;

            rocksdb::Options opts;
            opts.create_if_missing = create_new;
            opts.error_if_exists = create_new;
            opts.write_buffer_size = 40 * 1024; // 40 K for testing now

            auto status = rocksdb::DB::Open(opts, data_dir() + "/rdb", &_db);
            if (status.ok())
            {
                _is_open = true;
                _last_committed_decree = last_durable_decree();
            }

            return status.code();
        }

        int  rrdb_service_impl::close(bool clear_state)
        {
            if (!_is_open)
                return ERR_SERVICE_NOT_ACTIVE;

            _is_open = false;
            delete _db;
            _db = nullptr;

            if (clear_state)
            {
                boost::filesystem::path lp = data_dir();
                ::boost::filesystem::remove_all(lp);
                ::boost::filesystem::create_directory(lp);
            }
            return 0;
        }

        int  rrdb_service_impl::flush(bool force)
        {
            if (!_is_open)
                return ERR_SERVICE_NOT_ACTIVE;

            rocksdb::FlushOptions opts;
            opts.wait = force;

            auto status = _db->Flush(opts);
            return status.code();
        }

        void rrdb_service_impl::prepare_learning_request(__out_param blob& learn_req)
        {
            // nothing to do
        }

        int  rrdb_service_impl::get_learn_state(
            ::dsn::replication::decree start,
            const blob& learn_req,
            __out_param::dsn::replication::learn_state& state)
        {
            if (!_is_open)
                return ERR_SERVICE_NOT_ACTIVE;

            rocksdb::SequenceNumber start0 = start;
            rocksdb::SequenceNumber end;
            std::string mem_state;
            std::string edit;

            auto status = _db->GetLearningState(start0, end, mem_state, edit, state.files);
            if (status.ok())
            {
                binary_writer writer;
                writer.write(start0);
                writer.write(end);
                writer.write(edit);
                writer.write(mem_state);

                printf("GetLearningState result size = %d\n", writer.total_size());

                state.meta.push_back(writer.get_buffer());
            }

            return status.code();
        }

        int  rrdb_service_impl::apply_learn_state(::dsn::replication::learn_state& state)
        {
            if (!_is_open)
                return ERR_SERVICE_NOT_ACTIVE;

            binary_reader reader(state.meta[0]);

            printf("ApplyLearningState result size = %d\n", reader.total_size());

            rocksdb::SequenceNumber start;
            rocksdb::SequenceNumber end;
            std::string edit;
            std::string mem_state;

            reader.read(start);
            reader.read(end);
            reader.read(edit);
            reader.read(mem_state);

            if (mem_state.size() == 0 && state.files.size() == 0)
                return ERR_SUCCESS;
            else
            {
                if (start == 0)
                {
                    close(true);
                    open(true);
                }

                for (auto &f : state.files)
                {
                    boost::filesystem::path old_p = learn_dir() + f;
                    boost::filesystem::path new_p = data_dir() + f;

                    // create directory recursively if necessary
                    boost::filesystem::path path = new_p;
                    path = path.remove_filename();
                    if (!boost::filesystem::exists(path))
                        boost::filesystem::create_directories(path);

                    boost::filesystem::rename(old_p, new_p);
                }

                auto status = _db->ApplyLearningState(start, mem_state, edit);
                if (status.ok())
                {
                    _last_committed_decree = end;
                    printf("ApplyLeraningState lastcommitted in DB %s, <C,D> to <%lld, %lld> with <start,end> as <%lld, %lld>\n",
                        data_dir().c_str(),
                        static_cast<long long int>(last_committed_decree()),
                        static_cast<long long int>(last_durable_decree()),
                        static_cast<long long int>(start),
                        static_cast<long long int>(end)
                        );
                }
                return status.code();
            }
        }

        ::dsn::replication::decree rrdb_service_impl::last_durable_decree() const
        {
            if (_is_open)
                return _db->GetLatestDurableSequenceNumber();
            else
                return 0;
        }
    }
}
<commit_msg>increase last commit number as now the replication app base does not do that automatically and requires the local app itself to do that to ensure atomicity.<commit_after># include "rrdb.server.impl.h"
# include <boost/filesystem.hpp>

namespace dsn {
    namespace apps {
        rrdb_service_impl::rrdb_service_impl(::dsn::replication::replica* replica, ::dsn::configuration_ptr& config)
            : rrdb_service(replica, config)
        {
            _is_open = false;

            //
            // disable write ahead logging as replication handles logging instead now
            //
            _wt_opts.disableWAL = true;
        }

        void rrdb_service_impl::on_put(const update_request& update, ::dsn::service::rpc_replier<int>& reply)
        {
            if (_is_open)
            {
                rocksdb::WriteOptions opts = _wt_opts;
                opts.given_sequence_number = static_cast<rocksdb::SequenceNumber>(_last_committed_decree + 1);

                rocksdb::Slice skey(update.key.data(), update.key.length());
                rocksdb::Slice svalue(update.value.data(), update.value.length());
                rocksdb::Status status = _db->Put(opts, skey, svalue);
                reply(status.code());

                ++_last_committed_decree;
            }
            else
            {
                reply(ERR_SERVICE_NOT_ACTIVE);
            }
        }

        void rrdb_service_impl::on_remove(const ::dsn::blob& key, ::dsn::service::rpc_replier<int>& reply)
        {
            if (_is_open)
            {
                rocksdb::WriteOptions opts = _wt_opts;
                opts.given_sequence_number = static_cast<rocksdb::SequenceNumber>(_last_committed_decree + 1);

                rocksdb::Slice skey(key.data(), key.length());
                rocksdb::Status status = _db->Delete(opts, skey);
                reply(status.code());

                ++_last_committed_decree;
            }
            else
            {
                reply(ERR_SERVICE_NOT_ACTIVE);
            }
        }

        void rrdb_service_impl::on_merge(const update_request& update, ::dsn::service::rpc_replier<int>& reply)
        {
            if (_is_open)
            {
                rocksdb::WriteOptions opts = _wt_opts;
                opts.given_sequence_number = static_cast<rocksdb::SequenceNumber>(_last_committed_decree + 1);

                rocksdb::Slice skey(update.key.data(), update.key.length());
                rocksdb::Slice svalue(update.value.data(), update.value.length());
                rocksdb::Status status = _db->Merge(opts, skey, svalue);
                reply(status.code());

                ++_last_committed_decree;
            }
            else
            {
                reply(ERR_SERVICE_NOT_ACTIVE);
            }
        }

        void rrdb_service_impl::on_get(const ::dsn::blob& key, ::dsn::service::rpc_replier<read_response>& reply)
        {
            read_response resp;

            if (_is_open)
            {
                rocksdb::Slice skey(key.data(), key.length());
                rocksdb::Status status = _db->Get(_rd_opts, skey, &resp.value);
                resp.error = status.code();
            }
            else
            {
                resp.error = ERR_SERVICE_NOT_ACTIVE;
            }
            reply(resp);
        }

        int  rrdb_service_impl::open(bool create_new)
        {
            if (_is_open)
                return ERR_SERVICE_ALREADY_RUNNING;

            rocksdb::Options opts;
            opts.create_if_missing = create_new;
            opts.error_if_exists = create_new;
            opts.write_buffer_size = 40 * 1024; // 40 K for testing now

            auto status = rocksdb::DB::Open(opts, data_dir() + "/rdb", &_db);
            if (status.ok())
            {
                _is_open = true;
                _last_committed_decree = last_durable_decree();
            }

            return status.code();
        }

        int  rrdb_service_impl::close(bool clear_state)
        {
            if (!_is_open)
                return ERR_SERVICE_NOT_ACTIVE;

            _is_open = false;
            delete _db;
            _db = nullptr;

            if (clear_state)
            {
                boost::filesystem::path lp = data_dir();
                ::boost::filesystem::remove_all(lp);
                ::boost::filesystem::create_directory(lp);
            }
            return 0;
        }

        int  rrdb_service_impl::flush(bool force)
        {
            if (!_is_open)
                return ERR_SERVICE_NOT_ACTIVE;

            rocksdb::FlushOptions opts;
            opts.wait = force;

            auto status = _db->Flush(opts);
            return status.code();
        }

        void rrdb_service_impl::prepare_learning_request(__out_param blob& learn_req)
        {
            // nothing to do
        }

        int  rrdb_service_impl::get_learn_state(
            ::dsn::replication::decree start,
            const blob& learn_req,
            __out_param::dsn::replication::learn_state& state)
        {
            if (!_is_open)
                return ERR_SERVICE_NOT_ACTIVE;

            rocksdb::SequenceNumber start0 = start;
            rocksdb::SequenceNumber end;
            std::string mem_state;
            std::string edit;

            auto status = _db->GetLearningState(start0, end, mem_state, edit, state.files);
            if (status.ok())
            {
                binary_writer writer;
                writer.write(start0);
                writer.write(end);
                writer.write(edit);
                writer.write(mem_state);

                printf("GetLearningState result size = %d\n", writer.total_size());

                state.meta.push_back(writer.get_buffer());
            }

            return status.code();
        }

        int  rrdb_service_impl::apply_learn_state(::dsn::replication::learn_state& state)
        {
            if (!_is_open)
                return ERR_SERVICE_NOT_ACTIVE;

            binary_reader reader(state.meta[0]);

            printf("ApplyLearningState result size = %d\n", reader.total_size());

            rocksdb::SequenceNumber start;
            rocksdb::SequenceNumber end;
            std::string edit;
            std::string mem_state;

            reader.read(start);
            reader.read(end);
            reader.read(edit);
            reader.read(mem_state);

            if (mem_state.size() == 0 && state.files.size() == 0)
                return ERR_SUCCESS;
            else
            {
                if (start == 0)
                {
                    close(true);
                    open(true);
                }

                for (auto &f : state.files)
                {
                    boost::filesystem::path old_p = learn_dir() + f;
                    boost::filesystem::path new_p = data_dir() + f;

                    // create directory recursively if necessary
                    boost::filesystem::path path = new_p;
                    path = path.remove_filename();
                    if (!boost::filesystem::exists(path))
                        boost::filesystem::create_directories(path);

                    boost::filesystem::rename(old_p, new_p);
                }

                auto status = _db->ApplyLearningState(start, mem_state, edit);
                if (status.ok())
                {
                    _last_committed_decree = end;
                    printf("ApplyLeraningState lastcommitted in DB %s, <C,D> to <%lld, %lld> with <start,end> as <%lld, %lld>\n",
                        data_dir().c_str(),
                        static_cast<long long int>(last_committed_decree()),
                        static_cast<long long int>(last_durable_decree()),
                        static_cast<long long int>(start),
                        static_cast<long long int>(end)
                        );
                }
                return status.code();
            }
        }

        ::dsn::replication::decree rrdb_service_impl::last_durable_decree() const
        {
            if (_is_open)
                return _db->GetLatestDurableSequenceNumber();
            else
                return 0;
        }
    }
}
<|endoftext|>


<commit_before>#include "comparison_thread.h"
#include "freetype_interface.h"

FrameWinner::FrameWinner(char symb, uint_fast8_t diff)
    : symbol(symb)
    , grayLvlDiff(diff) {
}

SymbolMatches::SymbolMatches(size_t framesQuantity, const std::string& set)
    : progress(0)
    , symbolSet(set) {
    frameWinners.reserve(framesQuantity);
}

SymbolMatches::SymbolMatches(const SymbolMatches& toCopy)
    : frameWinners(toCopy.frameWinners)
    , progress(toCopy.progress.load())
    , symbolSet(toCopy.symbolSet) {
}

static uint_fast8_t calculateGrayLevelDiff( const FrameSlider& imgPart,
                                            const GrayscaleBitmap& glyph) {
    if (imgPart.size() != glyph.rows * glyph.columns) {
        throw std::runtime_error("Sizes of image part and symbol glyph do not match");
    }

    size_t pixelCount = imgPart.size();
    size_t diffAcc = 0;

    for (size_t pixelNum = 0; pixelNum < pixelCount; ++pixelNum) {
        diffAcc += abs(static_cast<int>(imgPart.at(pixelNum))
                        - glyph.pixels->at(pixelNum));
    }

    return diffAcc / pixelCount;
}

static FrameWinner chooseMatchingSymbol(const FrameSlider& imgPart,
                                        const std::string& symbolSet) {
    uint_fast8_t minDiff = 0xFF;
    char bestMatch = symbolSet.front();

    symbol_map vocabulary = getVocabulary();

    for (char symbol : symbolSet) {
        uint_fast8_t diff = calculateGrayLevelDiff(imgPart, vocabulary.at(symbol));

        if (diff < minDiff) {
            bestMatch = symbol;
            minDiff = diff;
        }
    }

    return FrameWinner(bestMatch, minDiff);
}

#include <iostream>
#include <exception>

void processVocabularyPart(const FramedBitmap* map, SymbolMatches* matches) {
    try {
        const FrameSlider lastFrame = map->lastFrame();
        FrameSlider       frame     = map->firstFrame();

        for (; frame != lastFrame; frame.slide()) {
            FrameWinner winner = chooseMatchingSymbol(frame, matches->symbolSet);
            matches->frameWinners.push_back(winner);
            ++matches->progress;
        }

        FrameWinner winner = chooseMatchingSymbol(lastFrame, matches->symbolSet);
        matches->frameWinners.push_back(winner);
        ++matches->progress;

    }
    catch (std::exception& err) {
        std::cerr << err.what() << std::endl;
    }
    catch (...) {
        std::cerr << "Unknown exception caught" << std::endl;
    }
}
<commit_msg>simpler cycle #9<commit_after>#include "comparison_thread.h"
#include "freetype_interface.h"

FrameWinner::FrameWinner(char symb, uint_fast8_t diff)
    : symbol(symb)
    , grayLvlDiff(diff) {
}

SymbolMatches::SymbolMatches(size_t framesQuantity, const std::string& set)
    : progress(0)
    , symbolSet(set) {
    frameWinners.reserve(framesQuantity);
}

SymbolMatches::SymbolMatches(const SymbolMatches& toCopy)
    : frameWinners(toCopy.frameWinners)
    , progress(toCopy.progress.load())
    , symbolSet(toCopy.symbolSet) {
}

static uint_fast8_t calculateGrayLevelDiff( const FrameSlider& imgPart,
                                            const GrayscaleBitmap& glyph) {
    if (imgPart.size() != glyph.rows * glyph.columns) {
        throw std::runtime_error("Sizes of image part and symbol glyph do not match");
    }

    size_t pixelCount = imgPart.size();
    size_t diffAcc = 0;

    for (size_t pixelNum = 0; pixelNum < pixelCount; ++pixelNum) {
        diffAcc += abs(static_cast<int>(imgPart.at(pixelNum))
                        - glyph.pixels->at(pixelNum));
    }

    return diffAcc / pixelCount;
}

static FrameWinner chooseMatchingSymbol(const FrameSlider& imgPart,
                                        const std::string& symbolSet) {
    uint_fast8_t minDiff = 0xFF;
    char bestMatch = symbolSet.front();

    symbol_map vocabulary = getVocabulary();

    for (char symbol : symbolSet) {
        uint_fast8_t diff = calculateGrayLevelDiff(imgPart, vocabulary.at(symbol));

        if (diff < minDiff) {
            bestMatch = symbol;
            minDiff = diff;
        }
    }

    return FrameWinner(bestMatch, minDiff);
}

#include <iostream>
#include <exception>

void processVocabularyPart(const FramedBitmap* map, SymbolMatches* matches) {
    try {
        const FrameSlider lastFrame = map->lastFrame();

        for (FrameSlider frame = map->firstFrame(); frame != lastFrame; frame.slide()) {
            FrameWinner winner = chooseMatchingSymbol(frame, matches->symbolSet);
            matches->frameWinners.push_back(winner);
            ++matches->progress;
        }

        FrameWinner winner = chooseMatchingSymbol(lastFrame, matches->symbolSet);
        matches->frameWinners.push_back(winner);
        ++matches->progress;

    }
    catch (std::exception& err) {
        std::cerr << err.what() << std::endl;
    }
    catch (...) {
        std::cerr << "Unknown exception caught" << std::endl;
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Google Inc. 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 "components/player.h"

#include "btBulletDynamicsCommon.h"
#include "component_library/physics.h"
#include "component_library/transform.h"
#include "components/player_projectile.h"
#include "components/rail_denizen.h"
#include "components/services.h"
#include "entity/entity_common.h"
#include "event/event_manager.h"
#include "events/parse_action.h"
#include "fplbase/flatbuffer_utils.h"
#include "fplbase/utilities.h"
#include "mathfu/constants.h"
#include "mathfu/glsl_mappings.h"
#include "world.h"

FPL_ENTITY_DEFINE_COMPONENT(fpl::fpl_project::PlayerComponent,
                            fpl::fpl_project::PlayerData)

namespace fpl {
namespace fpl_project {

using fpl::component_library::PhysicsComponent;
using fpl::component_library::PhysicsData;
using fpl::component_library::TransformComponent;
using fpl::component_library::TransformData;

static const float kDegreesToRadians = M_PI / 180.0f;

void PlayerComponent::Init() {
  config_ = entity_manager_->GetComponent<ServicesComponent>()->config();
  event_manager_ =
      entity_manager_->GetComponent<ServicesComponent>()->event_manager();
}

void PlayerComponent::UpdateAllEntities(entity::WorldTime /*delta_time*/) {
  for (auto iter = component_data_.begin(); iter != component_data_.end();
       ++iter) {
    PlayerData* player_data = Data<PlayerData>(iter->entity);
    TransformData* transform_data = Data<TransformData>(iter->entity);
    if (active_) {
      player_data->input_controller()->Update();
    }
    transform_data->orientation =
        mathfu::quat::RotateFromTo(player_data->GetFacing(), mathfu::kAxisY3f);
    if (player_data->input_controller()->Button(kFireProjectile).Value() &&
        player_data->input_controller()->Button(kFireProjectile).HasChanged()) {
      SpawnProjectile(iter->entity);
      EventContext context;
      context.source = iter->entity;
      context.raft =
          entity_manager_->GetComponent<ServicesComponent>()->raft_entity();
      ParseAction(player_data->on_fire(), &context, event_manager_,
                  entity_manager_);
    }
  }
}

void PlayerComponent::AddFromRawData(entity::EntityRef& entity,
                                     const void* raw_data) {
  auto player_def = static_cast<const PlayerDef*>(raw_data);
  PlayerData* player_data = AddEntity(entity);
  player_data->set_on_fire(player_def->on_fire());
}

void PlayerComponent::InitEntity(entity::EntityRef& entity) {
  entity_manager_->AddEntityToComponent<TransformComponent>(entity);
}

entity::EntityRef PlayerComponent::SpawnProjectile(entity::EntityRef source) {
  entity::EntityRef projectile =
      entity_manager_->GetComponent<ServicesComponent>()
          ->entity_factory()
          ->CreateEntityFromPrototype("Projectile", entity_manager_);

  TransformData* transform_data = Data<TransformData>(projectile);
  PhysicsData* physics_data = Data<PhysicsData>(projectile);
  PlayerProjectileData* projectile_data =
      Data<PlayerProjectileData>(projectile);

  TransformComponent* transform_component = GetComponent<TransformComponent>();
  transform_data->position = transform_component->WorldPosition(source) +
                             LoadVec3(config_->projectile_offset());
  transform_data->orientation = transform_component->WorldOrientation(source);
  vec3 forward = transform_data->orientation.Inverse() * mathfu::kAxisY3f;

  vec3 velocity = config_->projectile_speed() * forward +
                  config_->projectile_upkick() * mathfu::kAxisZ3f;

  // Include the raft's current velocity to the thrown sushi.
  auto raft_entity =
      entity_manager_->GetComponent<ServicesComponent>()->raft_entity();
  auto raft_rail = raft_entity ? Data<RailDenizenData>(raft_entity) : nullptr;
  if (raft_rail != nullptr) velocity += raft_rail->Velocity();

  physics_data->SetVelocity(velocity);
  physics_data->SetAngularVelocity(vec3(mathfu::RandomInRange(3.0f, 6.0f),
                                        mathfu::RandomInRange(3.0f, 6.0f),
                                        mathfu::RandomInRange(3.0f, 6.0f)));
  auto physics_component = entity_manager_->GetComponent<PhysicsComponent>();
  physics_component->UpdatePhysicsFromTransform(projectile);

  projectile_data->owner = source;

  return entity::EntityRef();
}

entity::ComponentInterface::RawDataUniquePtr PlayerComponent::ExportRawData(
    entity::EntityRef& entity) const {
  const PlayerData* data = GetComponentData(entity);
  if (data == nullptr) return nullptr;

  flatbuffers::FlatBufferBuilder fbb;

  // TODO: output the on_fire events.
  PlayerDefBuilder builder(fbb);

  fbb.Finish(builder.Finish());
  return fbb.ReleaseBufferPointer();
}

}  // fpl_project
}  // fpl
<commit_msg>Removing unused constant in player<commit_after>// Copyright 2015 Google Inc. 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 "components/player.h"

#include "btBulletDynamicsCommon.h"
#include "component_library/physics.h"
#include "component_library/transform.h"
#include "components/player_projectile.h"
#include "components/rail_denizen.h"
#include "components/services.h"
#include "entity/entity_common.h"
#include "event/event_manager.h"
#include "events/parse_action.h"
#include "fplbase/flatbuffer_utils.h"
#include "fplbase/utilities.h"
#include "mathfu/constants.h"
#include "mathfu/glsl_mappings.h"
#include "world.h"

FPL_ENTITY_DEFINE_COMPONENT(fpl::fpl_project::PlayerComponent,
                            fpl::fpl_project::PlayerData)

namespace fpl {
namespace fpl_project {

using fpl::component_library::PhysicsComponent;
using fpl::component_library::PhysicsData;
using fpl::component_library::TransformComponent;
using fpl::component_library::TransformData;

void PlayerComponent::Init() {
  config_ = entity_manager_->GetComponent<ServicesComponent>()->config();
  event_manager_ =
      entity_manager_->GetComponent<ServicesComponent>()->event_manager();
}

void PlayerComponent::UpdateAllEntities(entity::WorldTime /*delta_time*/) {
  for (auto iter = component_data_.begin(); iter != component_data_.end();
       ++iter) {
    PlayerData* player_data = Data<PlayerData>(iter->entity);
    TransformData* transform_data = Data<TransformData>(iter->entity);
    if (active_) {
      player_data->input_controller()->Update();
    }
    transform_data->orientation =
        mathfu::quat::RotateFromTo(player_data->GetFacing(), mathfu::kAxisY3f);
    if (player_data->input_controller()->Button(kFireProjectile).Value() &&
        player_data->input_controller()->Button(kFireProjectile).HasChanged()) {
      SpawnProjectile(iter->entity);
      EventContext context;
      context.source = iter->entity;
      context.raft =
          entity_manager_->GetComponent<ServicesComponent>()->raft_entity();
      ParseAction(player_data->on_fire(), &context, event_manager_,
                  entity_manager_);
    }
  }
}

void PlayerComponent::AddFromRawData(entity::EntityRef& entity,
                                     const void* raw_data) {
  auto player_def = static_cast<const PlayerDef*>(raw_data);
  PlayerData* player_data = AddEntity(entity);
  player_data->set_on_fire(player_def->on_fire());
}

void PlayerComponent::InitEntity(entity::EntityRef& entity) {
  entity_manager_->AddEntityToComponent<TransformComponent>(entity);
}

entity::EntityRef PlayerComponent::SpawnProjectile(entity::EntityRef source) {
  entity::EntityRef projectile =
      entity_manager_->GetComponent<ServicesComponent>()
          ->entity_factory()
          ->CreateEntityFromPrototype("Projectile", entity_manager_);

  TransformData* transform_data = Data<TransformData>(projectile);
  PhysicsData* physics_data = Data<PhysicsData>(projectile);
  PlayerProjectileData* projectile_data =
      Data<PlayerProjectileData>(projectile);

  TransformComponent* transform_component = GetComponent<TransformComponent>();
  transform_data->position = transform_component->WorldPosition(source) +
                             LoadVec3(config_->projectile_offset());
  transform_data->orientation = transform_component->WorldOrientation(source);
  vec3 forward = transform_data->orientation.Inverse() * mathfu::kAxisY3f;

  vec3 velocity = config_->projectile_speed() * forward +
                  config_->projectile_upkick() * mathfu::kAxisZ3f;

  // Include the raft's current velocity to the thrown sushi.
  auto raft_entity =
      entity_manager_->GetComponent<ServicesComponent>()->raft_entity();
  auto raft_rail = raft_entity ? Data<RailDenizenData>(raft_entity) : nullptr;
  if (raft_rail != nullptr) velocity += raft_rail->Velocity();

  physics_data->SetVelocity(velocity);
  physics_data->SetAngularVelocity(vec3(mathfu::RandomInRange(3.0f, 6.0f),
                                        mathfu::RandomInRange(3.0f, 6.0f),
                                        mathfu::RandomInRange(3.0f, 6.0f)));
  auto physics_component = entity_manager_->GetComponent<PhysicsComponent>();
  physics_component->UpdatePhysicsFromTransform(projectile);

  projectile_data->owner = source;

  return entity::EntityRef();
}

entity::ComponentInterface::RawDataUniquePtr PlayerComponent::ExportRawData(
    entity::EntityRef& entity) const {
  const PlayerData* data = GetComponentData(entity);
  if (data == nullptr) return nullptr;

  flatbuffers::FlatBufferBuilder fbb;

  // TODO: output the on_fire events.
  PlayerDefBuilder builder(fbb);

  fbb.Finish(builder.Finish());
  return fbb.ReleaseBufferPointer();
}

}  // fpl_project
}  // fpl
<|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/framework/ir/conv_elementwise_add_mkldnn_fuse_pass.h"
#include <functional>

#include "paddle/fluid/framework/ir/graph_traits.h"

namespace paddle {
namespace framework {
namespace ir {
namespace {
void CorrectGraphEdges(Graph* graph, Node* from, Node* to) {
  for (auto& node : GraphTraits::DFS(*graph)) {
    auto from_in_inputs =
        std::find(std::begin(node.inputs), std::end(node.inputs), from);

    if (from_in_inputs != std::end(node.inputs)) {
      IR_NODE_LINK_TO(to, (&node));

      auto inputs = node.Op()->Inputs();

      using input_type = VariableNameMap::value_type;

      std::for_each(std::begin(inputs), std::end(inputs),
                    [from, to, &node](const input_type& i) -> void {
                      auto param_names = i.second;
                      auto pi = std::find(std::begin(param_names),
                                          std::end(param_names), from->Name());

                      if (pi != std::end(param_names)) {
                        node.Op()->SetInput(i.first, {to->Name()});
                      }
                    });
    }
  }
}
}  // namespace
using graph_ptr = std::unique_ptr<ir::Graph>;

graph_ptr ConvElementwiseAddMKLDNNFusePass::ApplyImpl(graph_ptr graph) const {
  FusePassBase::Init("conv_elementwise_add_mkldnn_fuse_pass", graph.get());

  GraphPatternDetector gpd;
  auto pattern = gpd.mutable_pattern();

  patterns::Conv conv_pattern{pattern, "skip_connections_fusion"};
  auto conv_output = conv_pattern();

  patterns::ElementwiseAdd elementwise_add_pattern{pattern,
                                                   "skip_connections_fusion"};
  elementwise_add_pattern(conv_output);

  conv_output->AsIntermediate();

  auto handler = [&](const GraphPatternDetector::subgraph_t& subgraph,
                     Graph* g) {
    GET_IR_NODE_FROM_SUBGRAPH(conv_op, conv_op, conv_pattern);
    GET_IR_NODE_FROM_SUBGRAPH(conv_input, conv_input, conv_pattern);
    GET_IR_NODE_FROM_SUBGRAPH(conv_bias, conv_bias, conv_pattern);
    GET_IR_NODE_FROM_SUBGRAPH(conv_filter, conv_filter, conv_pattern);
    GET_IR_NODE_FROM_SUBGRAPH(conv_output, conv_output, conv_pattern);
    GET_IR_NODE_FROM_SUBGRAPH(elementwise_add_op, elementwise_add_op,
                              elementwise_add_pattern);
    GET_IR_NODE_FROM_SUBGRAPH(elementwise_add_x, elementwise_add_x,
                              elementwise_add_pattern);
    GET_IR_NODE_FROM_SUBGRAPH(elementwise_add_out, elementwise_add_out,
                              elementwise_add_pattern);

    OpDesc op_desc;
    op_desc.SetType("conv2d");

    op_desc.SetInput("Input", {conv_input->Name()});
    op_desc.SetInput("Bias", {conv_bias->Name()});
    op_desc.SetInput("Filter", {conv_filter->Name()});
    op_desc.SetInput("ResidualData", {elementwise_add_x->Name()});
    op_desc.SetOutput("Output", {conv_output->Name()});

    for (const auto& attr : conv_op->Op()->GetAttrMap()) {
      op_desc.SetAttr(attr.first, attr.second);
    }

    op_desc.SetAttr("fuse_residual_connection", true);

    auto fused_conv_op = g->CreateOpNode(&op_desc);

    IR_NODE_LINK_TO(conv_input, fused_conv_op);
    IR_NODE_LINK_TO(conv_bias, fused_conv_op);
    IR_NODE_LINK_TO(conv_filter, fused_conv_op);
    IR_NODE_LINK_TO(elementwise_add_x, fused_conv_op);
    IR_NODE_LINK_TO(fused_conv_op, conv_output);

    CorrectGraphEdges(g, elementwise_add_out, conv_output);
    GraphSafeRemoveNodes(g, {elementwise_add_out, conv_op, elementwise_add_op});
  };

  gpd(graph.get(), handler);

  return graph;
}
}  // namespace ir
}  // namespace framework
}  // namespace paddle

REGISTER_PASS(conv_elementwise_add_mkldnn_fuse_pass,
              paddle::framework::ir::ConvElementwiseAddMKLDNNFusePass);
<commit_msg>MKLDNN conv + elementwise_add fusion: comment explaining CorrectGraphEdges added<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/framework/ir/conv_elementwise_add_mkldnn_fuse_pass.h"
#include <functional>

#include "paddle/fluid/framework/ir/graph_traits.h"

namespace paddle {
namespace framework {
namespace ir {
namespace {

// The function keeps the graph consistent by replacing
// a node 'from' in the set of inputs nodes
// of the visited node by a node 'to'.
void CorrectGraphEdges(Graph* graph, Node* from, Node* to) {
  for (auto& node : GraphTraits::DFS(*graph)) {
    auto from_in_inputs =
        std::find(std::begin(node.inputs), std::end(node.inputs), from);

    if (from_in_inputs != std::end(node.inputs)) {
      IR_NODE_LINK_TO(to, (&node));

      auto inputs = node.Op()->Inputs();

      using input_type = VariableNameMap::value_type;

      std::for_each(std::begin(inputs), std::end(inputs),
                    [from, to, &node](const input_type& i) -> void {
                      auto param_names = i.second;
                      auto pi = std::find(std::begin(param_names),
                                          std::end(param_names), from->Name());

                      if (pi != std::end(param_names)) {
                        node.Op()->SetInput(i.first, {to->Name()});
                      }
                    });
    }
  }
}
}  // namespace
using graph_ptr = std::unique_ptr<ir::Graph>;

graph_ptr ConvElementwiseAddMKLDNNFusePass::ApplyImpl(graph_ptr graph) const {
  FusePassBase::Init("conv_elementwise_add_mkldnn_fuse_pass", graph.get());

  GraphPatternDetector gpd;
  auto pattern = gpd.mutable_pattern();

  patterns::Conv conv_pattern{pattern, "skip_connections_fusion"};
  auto conv_output = conv_pattern();

  patterns::ElementwiseAdd elementwise_add_pattern{pattern,
                                                   "skip_connections_fusion"};
  elementwise_add_pattern(conv_output);

  conv_output->AsIntermediate();

  auto handler = [&](const GraphPatternDetector::subgraph_t& subgraph,
                     Graph* g) {
    GET_IR_NODE_FROM_SUBGRAPH(conv_op, conv_op, conv_pattern);
    GET_IR_NODE_FROM_SUBGRAPH(conv_input, conv_input, conv_pattern);
    GET_IR_NODE_FROM_SUBGRAPH(conv_bias, conv_bias, conv_pattern);
    GET_IR_NODE_FROM_SUBGRAPH(conv_filter, conv_filter, conv_pattern);
    GET_IR_NODE_FROM_SUBGRAPH(conv_output, conv_output, conv_pattern);
    GET_IR_NODE_FROM_SUBGRAPH(elementwise_add_op, elementwise_add_op,
                              elementwise_add_pattern);
    GET_IR_NODE_FROM_SUBGRAPH(elementwise_add_x, elementwise_add_x,
                              elementwise_add_pattern);
    GET_IR_NODE_FROM_SUBGRAPH(elementwise_add_out, elementwise_add_out,
                              elementwise_add_pattern);

    OpDesc op_desc;
    op_desc.SetType("conv2d");

    op_desc.SetInput("Input", {conv_input->Name()});
    op_desc.SetInput("Bias", {conv_bias->Name()});
    op_desc.SetInput("Filter", {conv_filter->Name()});
    op_desc.SetInput("ResidualData", {elementwise_add_x->Name()});
    op_desc.SetOutput("Output", {conv_output->Name()});

    for (const auto& attr : conv_op->Op()->GetAttrMap()) {
      op_desc.SetAttr(attr.first, attr.second);
    }

    op_desc.SetAttr("fuse_residual_connection", true);

    auto fused_conv_op = g->CreateOpNode(&op_desc);

    IR_NODE_LINK_TO(conv_input, fused_conv_op);
    IR_NODE_LINK_TO(conv_bias, fused_conv_op);
    IR_NODE_LINK_TO(conv_filter, fused_conv_op);
    IR_NODE_LINK_TO(elementwise_add_x, fused_conv_op);
    IR_NODE_LINK_TO(fused_conv_op, conv_output);

    CorrectGraphEdges(g, elementwise_add_out, conv_output);
    GraphSafeRemoveNodes(g, {elementwise_add_out, conv_op, elementwise_add_op});
  };

  gpd(graph.get(), handler);

  return graph;
}
}  // namespace ir
}  // namespace framework
}  // namespace paddle

REGISTER_PASS(conv_elementwise_add_mkldnn_fuse_pass,
              paddle::framework::ir::ConvElementwiseAddMKLDNNFusePass);
<|endoftext|>


<commit_before>// Catch
#include <catch.hpp>

// C++ Standard Library
#include <memory>
#include <iostream>

// Boost
#include <boost/filesystem.hpp>

// Armadillo
#include <armadillo>

// HOP
#include <hop>

extern boost::filesystem::path testDirectory;
static std::string dataPath_ = "/data/optimisationAlgorithm/trajectoryBasedAlgrorithm/hillClimbing/";

class TestHillClimbing : public hop::HillClimbing {
  public:
    TestHillClimbing(
        const std::shared_ptr<hop::OptimisationProblem> optimisationProblem)
      : HillClimbing(optimisationProblem),
        velocityIndex_(0){
    }

    arma::Col<double> getVelocity() {
      return velocities_.col(velocityIndex_++);
    }

    void setVelocitys(arma::mat velocities){
      velocities_ = velocities;
    }

  protected:
    unsigned int velocityIndex_;
    arma::mat velocities_;
};

class TestHillClimbingProblem : public hop::OptimisationProblem {
  public:
    TestHillClimbingProblem(
        const unsigned int numberOfDimensions)
      : OptimisationProblem(numberOfDimensions),
        ValueIndex_(0) {
    }

    std::vector<arma::Col<double>> getParameterHistory() const noexcept {
      return parameterHistory_;
    }

    void setObjectiveValues(arma::Col<double> objectiveValues){
      objectiveValues_ = objectiveValues;
    }

    void setSoftConstraintsValues(arma::Col<double> softConstraintsValues){
      softConstraintsValues_ = softConstraintsValues;
    }

  protected:
    unsigned int ValueIndex_;
    arma::Col<double> objectiveValues_;
    arma::Col<double> softConstraintsValues_;

    static std::vector<arma::Col<double>> parameterHistory_;

    double getObjectiveValueImplementation(
       const arma::Col<double>& parameter) const override {
       parameterHistory_.push_back(parameter);

      return objectiveValues_.at(ValueIndex_);
    }

    double getSoftConstraintsValueImplementation(
       const arma::Col<double>& parameter) const override {

      return softConstraintsValues_.at(ValueIndex_);
    }

    std::string to_string() const noexcept {
      return "TestHillClimbing";
    }
};

decltype(TestHillClimbingProblem::parameterHistory_) TestHillClimbingProblem::parameterHistory_;

TEST_CASE("Hill climbing", "") {

   // Set OptimisationProblem values
   arma::Col<double> upperBounds;
   upperBounds.load(testDirectory.string() + dataPath_ + "upperBounds.mat"); //the parametre is optional

   arma::Col<double> lowerBounds;
   lowerBounds.load(testDirectory.string() + dataPath_ + "lowerBounds.mat"); //the parametre is optional

   arma::Col<double> objectiveValues;
   objectiveValues.load(testDirectory.string() + dataPath_ + "objectiveValues[2.0].mat");

   arma::Col<double> softConstraintsValues;
   softConstraintsValues.load(testDirectory.string() + dataPath_ + "softConstraintsValues[2.0].mat");

   // Init OptimisationProblem
   std::shared_ptr<TestHillClimbingProblem> testHillClimbingProblem(new TestHillClimbingProblem(upperBounds.n_elem));
   testHillClimbingProblem->setUpperBounds(upperBounds);
   testHillClimbingProblem->setLowerBounds(lowerBounds);
   testHillClimbingProblem->setObjectiveValues(objectiveValues);
   testHillClimbingProblem->setSoftConstraintsValues(softConstraintsValues);

   // Set OptimisationAlgorithm values
   arma::mat velocities;
   velocities.load(testDirectory.string() + dataPath_ + "velocities[2.0].mat");

   arma::Col<double> initialParameter;
   initialParameter.load(testDirectory.string() + dataPath_ + "initialParameter[null].mat"); //the parametre is optional

   arma::Col<double> maximalStepSize;
   maximalStepSize.load(testDirectory.string() + dataPath_ + "maximalStepSize[2.1].mat"); //the parametre is optional

   // Init OptimisationAlgorithm
   TestHillClimbing testHillClimbing(testHillClimbingProblem);
   testHillClimbing.setVelocitys(velocities);
   testHillClimbing.setInitialParameter(initialParameter);
   testHillClimbing.setMaximalStepSize(maximalStepSize);

   // Set Expected values
   arma::Mat<double> expectedParameterHistory;
   expectedParameterHistory.load(testDirectory.string() + dataPath_ + "expected[2.1].mat");

   // Run hill climbing algorithm
  testHillClimbing.optimise();
  // Comparing of candidateParameters
  std::vector<arma::Col<double>> actualParameterHistory = testHillClimbingProblem->getParameterHistory();

  for(std::size_t n = 0; n < expectedParameterHistory.n_cols; ++n) {
    arma::Col<double> expectedParameter = expectedParameterHistory.col(n);
    arma::Col<double> actualParameter = actualParameterHistory.at(n);

    for (std::size_t k = 0; k < expectedParameter.n_elem; ++k) {
      CHECK(actualParameter.at(k) == Approx(expectedParameter.at(k)));
    }
  }
}

TEST_CASE("Hill climbing (init Test)", "") {

   // Set OptimisationProblem values
   arma::Col<double> upperBounds;
   upperBounds.load(testDirectory.string() + dataPath_ + "upperBounds.mat"); //the parametre is optional

   arma::Col<double> lowerBounds;
   lowerBounds.load(testDirectory.string() + dataPath_ + "lowerBounds.mat"); //the parametre is optional

   arma::Col<double> objectiveValues;
   objectiveValues.load(testDirectory.string() + dataPath_ + "objectiveValues[1.0].mat");

   arma::Col<double> softConstraintsValues;
   softConstraintsValues.load(testDirectory.string() + dataPath_ + "softConstraintsValues[1.0].mat");

   // Init OptimisationProblem
   std::shared_ptr<TestHillClimbingProblem> testHillClimbingProblem(new TestHillClimbingProblem(upperBounds.n_elem));
   testHillClimbingProblem->setUpperBounds(upperBounds);
   testHillClimbingProblem->setLowerBounds(lowerBounds);
   testHillClimbingProblem->setObjectiveValues(objectiveValues);
   testHillClimbingProblem->setSoftConstraintsValues(softConstraintsValues);

   // Set OptimisationAlgorithm values
   arma::mat velocities;
   velocities.load(testDirectory.string() + dataPath_ + "velocities[1.0].mat");

   // Init OptimisationAlgorithm
   TestHillClimbing testHillClimbing(testHillClimbingProblem);
   testHillClimbing.setVelocitys(velocities);

   arma::Mat<double> expectedParameterHistory;

  SECTION("Check MaximalStepSize"){
    arma::Col<double> initialParameter;
    initialParameter.load(testDirectory.string() + dataPath_ + "initialParameter[null].mat"); //the parametre is optional

    //arma::Col<double> maximalStepSize;
    //maximalStepSize.load(testDirectory.string() + dataPath_ + "maximalStepSize[1.1].mat"); //the parametre is optional

    expectedParameterHistory.load(testDirectory.string() + dataPath_ + "expected[1.1].mat");

    testHillClimbing.setInitialParameter(initialParameter);
    //testHillClimbing.setMaximalStepSize(maximalStepSize);
    testHillClimbing.optimise();

    // Comparing of candidateParameters
    std::vector<arma::Col<double>> actualParameterHistory = testHillClimbingProblem->getParameterHistory();

    for(std::size_t n = 0; n < expectedParameterHistory.n_cols; ++n) {
      arma::Col<double> expectedParameter = expectedParameterHistory.col(n);
      arma::Col<double> actualParameter = actualParameterHistory.at(n);

      for (std::size_t k = 0; k < expectedParameter.n_elem; ++k) {
        CHECK(actualParameter.at(k) == Approx(expectedParameter.at(k)));
      }
    }

  }

}
<commit_msg>test: Added test for HillClimbing<commit_after>// Catch
#include <catch.hpp>

// C++ Standard Library
#include <memory>
#include <iostream>

// Boost
#include <boost/filesystem.hpp>

// Armadillo
#include <armadillo>

// HOP
#include <hop>

extern boost::filesystem::path testDirectory;
static std::string dataPath_ = "/data/optimisationAlgorithm/trajectoryBasedAlgrorithm/hillClimbing/";

class TestHillClimbing : public hop::HillClimbing {
  public:
    TestHillClimbing(
        const std::shared_ptr<hop::OptimisationProblem> optimisationProblem)
      : HillClimbing(optimisationProblem),
        velocityIndex_(0){
    }

    arma::Col<double> getVelocity() override {
      return velocities_.col(velocityIndex_++);
    }

    void setVelocitys(arma::mat velocities){
      velocities_ = velocities;
    }

  protected:
    unsigned int velocityIndex_;
    arma::mat velocities_;
};

class TestHillClimbingProblem : public hop::OptimisationProblem {
  public:
    TestHillClimbingProblem(
        const unsigned int numberOfDimensions)
      : OptimisationProblem(numberOfDimensions) {
      softConstraintsValuesIndex_ = 0;
      objectiveValuesIndex_ = 0;
    }

    std::vector<arma::Col<double>> getParameterHistory() const noexcept {
      return parameterHistory_;
    }

    void setObjectiveValues(arma::Col<double> objectiveValues){
      objectiveValues_ = objectiveValues;
    }

    void setSoftConstraintsValues(arma::Col<double> softConstraintsValues){
      softConstraintsValues_ = softConstraintsValues;
    }

  protected:
    static unsigned int softConstraintsValuesIndex_;
    static unsigned int objectiveValuesIndex_;
    arma::Col<double> objectiveValues_;
    arma::Col<double> softConstraintsValues_;

    static std::vector<arma::Col<double>> parameterHistory_;

    double getSoftConstraintsValueImplementation(
       const arma::Col<double>& parameter) const override {

      return softConstraintsValues_.at(softConstraintsValuesIndex_++);
    }

    double getObjectiveValueImplementation(
       const arma::Col<double>& parameter) const override {
       parameterHistory_.push_back(parameter);

      return objectiveValues_.at(objectiveValuesIndex_++);
    }

    std::string to_string() const noexcept {
      return "TestHillClimbing";
    }
};

decltype(TestHillClimbingProblem::parameterHistory_) TestHillClimbingProblem::parameterHistory_;
decltype(TestHillClimbingProblem::softConstraintsValuesIndex_) TestHillClimbingProblem::softConstraintsValuesIndex_;
decltype(TestHillClimbingProblem::objectiveValuesIndex_) TestHillClimbingProblem::objectiveValuesIndex_;

TEST_CASE("Hill climbing", "") {

   // Set OptimisationProblem values
   arma::Col<double> upperBounds;
   upperBounds.load(testDirectory.string() + dataPath_ + "upperBounds.mat"); //the parametre is optional

   arma::Col<double> lowerBounds;
   lowerBounds.load(testDirectory.string() + dataPath_ + "lowerBounds.mat"); //the parametre is optional

   arma::Col<double> objectiveValues;
   objectiveValues.load(testDirectory.string() + dataPath_ + "objectiveValues[2.0].mat");

   arma::Col<double> softConstraintsValues;
   softConstraintsValues.load(testDirectory.string() + dataPath_ + "softConstraintsValues[2.0].mat");

   // Init OptimisationProblem
   std::shared_ptr<TestHillClimbingProblem> testHillClimbingProblem(new TestHillClimbingProblem(upperBounds.n_elem));
   testHillClimbingProblem->setUpperBounds(upperBounds);
   testHillClimbingProblem->setLowerBounds(lowerBounds);
   testHillClimbingProblem->setObjectiveValues(objectiveValues);
   testHillClimbingProblem->setSoftConstraintsValues(softConstraintsValues);

   // Set OptimisationAlgorithm values
   arma::mat velocities;
   velocities.load(testDirectory.string() + dataPath_ + "velocities[2.0].mat");

   arma::Col<double> initialParameter;
   initialParameter.load(testDirectory.string() + dataPath_ + "initialParameter[null].mat"); //the parametre is optional

   arma::Col<double> maximalStepSize;
   maximalStepSize.load(testDirectory.string() + dataPath_ + "maximalStepSize[2.1].mat"); //the parametre is optional

   // Init OptimisationAlgorithm
   TestHillClimbing testHillClimbing(testHillClimbingProblem);
   testHillClimbing.setVelocitys(velocities);
   testHillClimbing.setInitialParameter(initialParameter);
   testHillClimbing.setMaximalStepSize(maximalStepSize);

   // Set Expected values
   arma::Mat<double> expectedParameterHistory;
   expectedParameterHistory.load(testDirectory.string() + dataPath_ + "expected[2.1].mat");

   // Run hill climbing algorithm
  testHillClimbing.optimise();
  // Comparing of candidateParameters
  std::vector<arma::Col<double>> actualParameterHistory = testHillClimbingProblem->getParameterHistory();

  for(std::size_t n = 0; n < expectedParameterHistory.n_cols; ++n) {
    arma::Col<double> expectedParameter = expectedParameterHistory.col(n);
    arma::Col<double> actualParameter = actualParameterHistory.at(n);

    for (std::size_t k = 0; k < expectedParameter.n_elem; ++k) {
      CHECK(actualParameter.at(k) == Approx(expectedParameter.at(k)));
    }
  }
}

TEST_CASE("Hill climbing (init Test)", "") {

   // Set OptimisationProblem values
   arma::Col<double> upperBounds;
   upperBounds.load(testDirectory.string() + dataPath_ + "upperBounds.mat"); //the parametre is optional

   arma::Col<double> lowerBounds;
   lowerBounds.load(testDirectory.string() + dataPath_ + "lowerBounds.mat"); //the parametre is optional

   arma::Col<double> objectiveValues;
   objectiveValues.load(testDirectory.string() + dataPath_ + "objectiveValues[1.0].mat");

   arma::Col<double> softConstraintsValues;
   softConstraintsValues.load(testDirectory.string() + dataPath_ + "softConstraintsValues[1.0].mat");

   // Init OptimisationProblem
   std::shared_ptr<TestHillClimbingProblem> testHillClimbingProblem(new TestHillClimbingProblem(upperBounds.n_elem));
   testHillClimbingProblem->setUpperBounds(upperBounds);
   testHillClimbingProblem->setLowerBounds(lowerBounds);
   testHillClimbingProblem->setObjectiveValues(objectiveValues);
   testHillClimbingProblem->setSoftConstraintsValues(softConstraintsValues);

   // Set OptimisationAlgorithm values
   arma::mat velocities;
   velocities.load(testDirectory.string() + dataPath_ + "velocities[1.0].mat");

   // Init OptimisationAlgorithm
   TestHillClimbing testHillClimbing(testHillClimbingProblem);
   testHillClimbing.setVelocitys(velocities);

   arma::Mat<double> expectedParameterHistory;

  SECTION("Check MaximalStepSize"){
    arma::Col<double> initialParameter;
    initialParameter.load(testDirectory.string() + dataPath_ + "initialParameter[null].mat"); //the parametre is optional

    //arma::Col<double> maximalStepSize;
    //maximalStepSize.load(testDirectory.string() + dataPath_ + "maximalStepSize[1.1].mat"); //the parametre is optional

    expectedParameterHistory.load(testDirectory.string() + dataPath_ + "expected[1.1].mat");

    testHillClimbing.setInitialParameter(initialParameter);
    //testHillClimbing.setMaximalStepSize(maximalStepSize);
    testHillClimbing.optimise();

    // Comparing of candidateParameters
    std::vector<arma::Col<double>> actualParameterHistory = testHillClimbingProblem->getParameterHistory();

    for(std::size_t n = 0; n < expectedParameterHistory.n_cols; ++n) {
      arma::Col<double> expectedParameter = expectedParameterHistory.col(n);
      arma::Col<double> actualParameter = actualParameterHistory.at(n);

      for (std::size_t k = 0; k < expectedParameter.n_elem; ++k) {
        CHECK(actualParameter.at(k) == Approx(expectedParameter.at(k)));
      }
    }

  }

}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <qtest.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
#include <QtQuick/private/qquicksmoothedanimation_p.h>
#include <QtQuick/private/qquickrectangle_p.h>
#include <private/qqmlvaluetype_p.h>
#include "../../shared/util.h"

class tst_qquicksmoothedanimation : public QQmlDataTest
{
    Q_OBJECT
public:
    tst_qquicksmoothedanimation();

private slots:
    void defaultValues();
    void values();
    void disabled();
    void simpleAnimation();
    void valueSource();
    void behavior();
    void deleteOnUpdate();
    void zeroDuration();

private:
    QQmlEngine engine;
};

tst_qquicksmoothedanimation::tst_qquicksmoothedanimation()
{
}

void tst_qquicksmoothedanimation::defaultValues()
{
    QQmlEngine engine;
    QQmlComponent c(&engine, testFileUrl("smoothedanimation1.qml"));
    QQuickSmoothedAnimation *obj = qobject_cast<QQuickSmoothedAnimation*>(c.create());

    QVERIFY(obj != 0);

    QCOMPARE(obj->to(), 0.);
    QCOMPARE(obj->velocity(), 200.);
    QCOMPARE(obj->duration(), -1);
    QCOMPARE(obj->maximumEasingTime(), -1);
    QCOMPARE(obj->reversingMode(), QQuickSmoothedAnimation::Eased);

    delete obj;
}

void tst_qquicksmoothedanimation::values()
{
    QQmlEngine engine;
    QQmlComponent c(&engine, testFileUrl("smoothedanimation2.qml"));
    QQuickSmoothedAnimation *obj = qobject_cast<QQuickSmoothedAnimation*>(c.create());

    QVERIFY(obj != 0);

    QCOMPARE(obj->to(), 10.);
    QCOMPARE(obj->velocity(), 200.);
    QCOMPARE(obj->duration(), 300);
    QCOMPARE(obj->maximumEasingTime(), -1);
    QCOMPARE(obj->reversingMode(), QQuickSmoothedAnimation::Immediate);

    delete obj;
}

void tst_qquicksmoothedanimation::disabled()
{
    QQmlEngine engine;
    QQmlComponent c(&engine, testFileUrl("smoothedanimation3.qml"));
    QQuickSmoothedAnimation *obj = qobject_cast<QQuickSmoothedAnimation*>(c.create());

    QVERIFY(obj != 0);

    QCOMPARE(obj->to(), 10.);
    QCOMPARE(obj->velocity(), 250.);
    QCOMPARE(obj->maximumEasingTime(), 150);
    QCOMPARE(obj->reversingMode(), QQuickSmoothedAnimation::Sync);

    delete obj;
}

void tst_qquicksmoothedanimation::simpleAnimation()
{
    QQmlEngine engine;
    QQmlComponent c(&engine, testFileUrl("simpleanimation.qml"));
    QObject *obj = c.create();
    QVERIFY(obj);

    QQuickRectangle *rect = obj->findChild<QQuickRectangle*>("rect");
    QVERIFY(rect);

    QQuickSmoothedAnimation *animation = obj->findChild<QQuickSmoothedAnimation*>("anim");
    QVERIFY(animation);

    animation->setTargetObject(rect);
    animation->setProperty("x");
    animation->setTo(200);
    animation->setDuration(250);
    QVERIFY(animation->target() == rect);
    QVERIFY(animation->property() == "x");
    QVERIFY(animation->to() == 200);
    animation->start();
    QVERIFY(animation->isRunning());
    QTest::qWait(animation->duration());
    QTRY_COMPARE(rect->x(), qreal(200));
    QTest::qWait(100);  //smoothed animation doesn't report stopped until delayed timer fires

    QVERIFY(!animation->isRunning());
    rect->setX(0);
    animation->start();
    QVERIFY(animation->isRunning());
    animation->pause();
    QVERIFY(animation->isRunning());
    QVERIFY(animation->isPaused());
    animation->setCurrentTime(125);
    QVERIFY(animation->currentTime() == 125);
    QCOMPARE(rect->x(), qreal(100));
}

void tst_qquicksmoothedanimation::valueSource()
{
    QQmlEngine engine;

    QQmlComponent c(&engine, testFileUrl("smoothedanimationValueSource.qml"));

    QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
    QVERIFY(rect);

    QQuickRectangle *theRect = rect->findChild<QQuickRectangle*>("theRect");
    QVERIFY(theRect);

    QQuickSmoothedAnimation *easeX = rect->findChild<QQuickSmoothedAnimation*>("easeX");
    QVERIFY(easeX);
    QVERIFY(easeX->isRunning());

    QQuickSmoothedAnimation *easeY = rect->findChild<QQuickSmoothedAnimation*>("easeY");
    QVERIFY(easeY);
    QVERIFY(easeY->isRunning());

    // XXX get the proper duration
    QTest::qWait(100);

    QTRY_VERIFY(!easeX->isRunning());
    QTRY_VERIFY(!easeY->isRunning());

    QTRY_COMPARE(theRect->x(), qreal(200));
    QTRY_COMPARE(theRect->y(), qreal(200));

    delete rect;
}

void tst_qquicksmoothedanimation::behavior()
{
#ifdef Q_CC_MINGW
    QSKIP("QTBUG-36290 - MinGW Animation tests are flaky.");
#endif
    QQmlEngine engine;

    QQmlComponent c(&engine, testFileUrl("smoothedanimationBehavior.qml"));

    QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
    QVERIFY(rect);

    QQuickRectangle *theRect = rect->findChild<QQuickRectangle*>("theRect");
    QVERIFY(theRect);

    QQuickSmoothedAnimation *easeX = rect->findChild<QQuickSmoothedAnimation*>("easeX");
    QVERIFY(easeX);

    QQuickSmoothedAnimation *easeY = rect->findChild<QQuickSmoothedAnimation*>("easeY");
    QVERIFY(easeY);

    // XXX get the proper duration
    QTest::qWait(400);

    QTRY_VERIFY(!easeX->isRunning());
    QTRY_VERIFY(!easeY->isRunning());

    QTRY_COMPARE(theRect->x(), qreal(200));
    QTRY_COMPARE(theRect->y(), qreal(200));

    delete rect;
}

void tst_qquicksmoothedanimation::deleteOnUpdate()
{
    QQmlEngine engine;

    QQmlComponent c(&engine, testFileUrl("deleteOnUpdate.qml"));

    QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
    QVERIFY(rect);

    QQuickSmoothedAnimation *anim = rect->findChild<QQuickSmoothedAnimation*>("anim");
    QVERIFY(anim);

    //don't crash
    QTest::qWait(500);

    delete rect;
}

void tst_qquicksmoothedanimation::zeroDuration()
{
    QQmlEngine engine;

    QQmlComponent c(&engine, testFileUrl("smoothedanimationZeroDuration.qml"));

    QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
    QVERIFY(rect);

    QQuickRectangle *theRect = rect->findChild<QQuickRectangle*>("theRect");
    QVERIFY(theRect);

    QQuickSmoothedAnimation *easeX = rect->findChild<QQuickSmoothedAnimation*>("easeX");
    QVERIFY(easeX);
    QVERIFY(easeX->isRunning());

    QTRY_VERIFY(!easeX->isRunning());
    QTRY_COMPARE(theRect->x(), qreal(200));

    delete rect;
}

QTEST_MAIN(tst_qquicksmoothedanimation)

#include "tst_qquicksmoothedanimation.moc"
<commit_msg>Verify empty SmoothedAnimation doesn't keep animation system running.<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <qtest.h>
#include <QtQml/qqmlengine.h>
#include <QtQml/qqmlcomponent.h>
#include <QtQuick/private/qquicksmoothedanimation_p.h>
#include <QtQuick/private/qquickrectangle_p.h>
#include <private/qqmlvaluetype_p.h>
#include "../../shared/util.h"

class tst_qquicksmoothedanimation : public QQmlDataTest
{
    Q_OBJECT
public:
    tst_qquicksmoothedanimation();

private slots:
    void defaultValues();
    void values();
    void disabled();
    void simpleAnimation();
    void valueSource();
    void behavior();
    void deleteOnUpdate();
    void zeroDuration();
    void noStart();

private:
    QQmlEngine engine;
};

tst_qquicksmoothedanimation::tst_qquicksmoothedanimation()
{
}

void tst_qquicksmoothedanimation::defaultValues()
{
    QQmlEngine engine;
    QQmlComponent c(&engine, testFileUrl("smoothedanimation1.qml"));
    QQuickSmoothedAnimation *obj = qobject_cast<QQuickSmoothedAnimation*>(c.create());

    QVERIFY(obj != 0);

    QCOMPARE(obj->to(), 0.);
    QCOMPARE(obj->velocity(), 200.);
    QCOMPARE(obj->duration(), -1);
    QCOMPARE(obj->maximumEasingTime(), -1);
    QCOMPARE(obj->reversingMode(), QQuickSmoothedAnimation::Eased);

    delete obj;
}

void tst_qquicksmoothedanimation::values()
{
    QQmlEngine engine;
    QQmlComponent c(&engine, testFileUrl("smoothedanimation2.qml"));
    QQuickSmoothedAnimation *obj = qobject_cast<QQuickSmoothedAnimation*>(c.create());

    QVERIFY(obj != 0);

    QCOMPARE(obj->to(), 10.);
    QCOMPARE(obj->velocity(), 200.);
    QCOMPARE(obj->duration(), 300);
    QCOMPARE(obj->maximumEasingTime(), -1);
    QCOMPARE(obj->reversingMode(), QQuickSmoothedAnimation::Immediate);

    delete obj;
}

void tst_qquicksmoothedanimation::disabled()
{
    QQmlEngine engine;
    QQmlComponent c(&engine, testFileUrl("smoothedanimation3.qml"));
    QQuickSmoothedAnimation *obj = qobject_cast<QQuickSmoothedAnimation*>(c.create());

    QVERIFY(obj != 0);

    QCOMPARE(obj->to(), 10.);
    QCOMPARE(obj->velocity(), 250.);
    QCOMPARE(obj->maximumEasingTime(), 150);
    QCOMPARE(obj->reversingMode(), QQuickSmoothedAnimation::Sync);

    delete obj;
}

void tst_qquicksmoothedanimation::simpleAnimation()
{
    QQmlEngine engine;
    QQmlComponent c(&engine, testFileUrl("simpleanimation.qml"));
    QObject *obj = c.create();
    QVERIFY(obj);

    QQuickRectangle *rect = obj->findChild<QQuickRectangle*>("rect");
    QVERIFY(rect);

    QQuickSmoothedAnimation *animation = obj->findChild<QQuickSmoothedAnimation*>("anim");
    QVERIFY(animation);

    animation->setTargetObject(rect);
    animation->setProperty("x");
    animation->setTo(200);
    animation->setDuration(250);
    QVERIFY(animation->target() == rect);
    QVERIFY(animation->property() == "x");
    QVERIFY(animation->to() == 200);
    animation->start();
    QVERIFY(animation->isRunning());
    QTest::qWait(animation->duration());
    QTRY_COMPARE(rect->x(), qreal(200));
    QTest::qWait(100);  //smoothed animation doesn't report stopped until delayed timer fires

    QVERIFY(!animation->isRunning());
    rect->setX(0);
    animation->start();
    QVERIFY(animation->isRunning());
    animation->pause();
    QVERIFY(animation->isRunning());
    QVERIFY(animation->isPaused());
    animation->setCurrentTime(125);
    QVERIFY(animation->currentTime() == 125);
    QCOMPARE(rect->x(), qreal(100));
}

void tst_qquicksmoothedanimation::valueSource()
{
    QQmlEngine engine;

    QQmlComponent c(&engine, testFileUrl("smoothedanimationValueSource.qml"));

    QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
    QVERIFY(rect);

    QQuickRectangle *theRect = rect->findChild<QQuickRectangle*>("theRect");
    QVERIFY(theRect);

    QQuickSmoothedAnimation *easeX = rect->findChild<QQuickSmoothedAnimation*>("easeX");
    QVERIFY(easeX);
    QVERIFY(easeX->isRunning());

    QQuickSmoothedAnimation *easeY = rect->findChild<QQuickSmoothedAnimation*>("easeY");
    QVERIFY(easeY);
    QVERIFY(easeY->isRunning());

    // XXX get the proper duration
    QTest::qWait(100);

    QTRY_VERIFY(!easeX->isRunning());
    QTRY_VERIFY(!easeY->isRunning());

    QTRY_COMPARE(theRect->x(), qreal(200));
    QTRY_COMPARE(theRect->y(), qreal(200));

    delete rect;
}

void tst_qquicksmoothedanimation::behavior()
{
#ifdef Q_CC_MINGW
    QSKIP("QTBUG-36290 - MinGW Animation tests are flaky.");
#endif
    QQmlEngine engine;

    QQmlComponent c(&engine, testFileUrl("smoothedanimationBehavior.qml"));

    QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
    QVERIFY(rect);

    QQuickRectangle *theRect = rect->findChild<QQuickRectangle*>("theRect");
    QVERIFY(theRect);

    QQuickSmoothedAnimation *easeX = rect->findChild<QQuickSmoothedAnimation*>("easeX");
    QVERIFY(easeX);

    QQuickSmoothedAnimation *easeY = rect->findChild<QQuickSmoothedAnimation*>("easeY");
    QVERIFY(easeY);

    // XXX get the proper duration
    QTest::qWait(400);

    QTRY_VERIFY(!easeX->isRunning());
    QTRY_VERIFY(!easeY->isRunning());

    QTRY_COMPARE(theRect->x(), qreal(200));
    QTRY_COMPARE(theRect->y(), qreal(200));

    delete rect;
}

void tst_qquicksmoothedanimation::deleteOnUpdate()
{
    QQmlEngine engine;

    QQmlComponent c(&engine, testFileUrl("deleteOnUpdate.qml"));

    QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
    QVERIFY(rect);

    QQuickSmoothedAnimation *anim = rect->findChild<QQuickSmoothedAnimation*>("anim");
    QVERIFY(anim);

    //don't crash
    QTest::qWait(500);

    delete rect;
}

void tst_qquicksmoothedanimation::zeroDuration()
{
    QQmlEngine engine;

    QQmlComponent c(&engine, testFileUrl("smoothedanimationZeroDuration.qml"));

    QQuickRectangle *rect = qobject_cast<QQuickRectangle*>(c.create());
    QVERIFY(rect);

    QQuickRectangle *theRect = rect->findChild<QQuickRectangle*>("theRect");
    QVERIFY(theRect);

    QQuickSmoothedAnimation *easeX = rect->findChild<QQuickSmoothedAnimation*>("easeX");
    QVERIFY(easeX);
    QVERIFY(easeX->isRunning());

    QTRY_VERIFY(!easeX->isRunning());
    QTRY_COMPARE(theRect->x(), qreal(200));

    delete rect;
}

//verify that an empty SmoothedAnimation does not fire up the animation system
//and keep it running forever
void tst_qquicksmoothedanimation::noStart()
{
    QQmlEngine engine;
    QQmlComponent c(&engine, testFileUrl("smoothedanimation1.qml"));
    QQuickSmoothedAnimation *obj = qobject_cast<QQuickSmoothedAnimation*>(c.create());

    QVERIFY(obj != 0);

    obj->start();
    QCOMPARE(obj->isRunning(), false);
    QTest::qWait(100);
    QCOMPARE(obj->isRunning(), false);
    //this could fail if the test is being run in parallel with other tests
    //or if an earlier test failed and didn't clean up (left an animation running)
    //QCOMPARE(QUnifiedTimer::instance()->runningAnimationCount(), 0);

    delete obj;
}

QTEST_MAIN(tst_qquicksmoothedanimation)

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