text: /******************************************************************************
   * The MIT License (MIT)
   *
   * Copyright (c) 2015-2017 Baldur Karlsson
   * Copyright (c) 2014 Crytek
   *
   * 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.
   ******************************************************************************/
  
  #pragma once
  
  #include <set>
  #include <vector>
  #include "api/replay/renderdoc_replay.h"
  #include "common/common.h"
  #include "core/core.h"
  #include "replay/replay_driver.h"
  #include "type_helpers.h"
  
  struct ReplayController;
  
  struct ReplayOutput : public IReplayOutput
  {
  public:
    void SetTextureDisplay(const TextureDisplay &o);
    void SetMeshDisplay(const MeshDisplay &o);
  
    void ClearThumbnails();
    bool AddThumbnail(WindowingSystem system, void *data, ResourceId texID, CompType typeHint);
  
    void Display();
  
    ReplayOutputType GetType() { return m_Type; }
    bool SetPixelContext(WindowingSystem system, void *data);
    void SetPixelContextLocation(uint32_t x, uint32_t y);
    void DisablePixelContext();
  
    rdctype::pair<PixelValue, PixelValue> GetMinMax();
    rdctype::array<uint32_t> GetHistogram(float minval, float maxval, bool channels[4]);
  
    ResourceId GetCustomShaderTexID() { return m_CustomShaderResourceId; }
    ResourceId GetDebugOverlayTexID() { return m_OverlayResourceId; }
    PixelValue PickPixel(ResourceId texID, bool customShader, uint32_t x, uint32_t y,
                         uint32_t sliceFace, uint32_t mip, uint32_t sample);
    rdctype::pair<uint32_t, uint32_t> PickVertex(uint32_t eventID, uint32_t x, uint32_t y);
  
  private:
    ReplayOutput(ReplayController *parent, WindowingSystem system, void *data, ReplayOutputType type);
    virtual ~ReplayOutput();
  
    void SetFrameEvent(int eventID);
  
    void RefreshOverlay();
  
    void DisplayContext();
    void DisplayTex();
  
    void DisplayMesh();
  
    ReplayController *m_pRenderer;
  
    bool m_OverlayDirty;
    bool m_ForceOverlayRefresh;
  
    IReplayDriver *m_pDevice;
  
    struct OutputPair
    {
      ResourceId texture;
      bool depthMode;
      uint64_t wndHandle;
      CompType typeHint;
      uint64_t outputID;
  
      bool dirty;
    } m_MainOutput;
  
    ResourceId m_OverlayResourceId;
    ResourceId m_CustomShaderResourceId;
  
    std::vector<OutputPair> m_Thumbnails;
  
    float m_ContextX;
    float m_ContextY;
    OutputPair m_PixelContext;
  
    uint32_t m_EventID;
    ReplayOutputType m_Type;
  
    vector<uint32_t> passEvents;
  
    int32_t m_Width;
    int32_t m_Height;
  
    struct
    {
      TextureDisplay texDisplay;
      MeshDisplay meshDisplay;
    } m_RenderData;
  
    friend struct ReplayController;
  };
  
  struct ReplayController : public IReplayController
  {
  public:
    ReplayController();
    virtual ~ReplayController();
  
    APIProperties GetAPIProperties();
  
    ReplayStatus CreateDevice(const char *logfile);
    ReplayStatus SetDevice(IReplayDriver *device);
  
    void FileChanged();
  
    bool HasCallstacks();
    bool InitResolver();
  
    void SetFrameEvent(uint32_t eventID, bool force);
  
    void FetchPipelineState();
  
    D3D11Pipe::State GetD3D11PipelineState();
    D3D12Pipe::State GetD3D12PipelineState();
    GLPipe::State GetGLPipelineState();
    VKPipe::State GetVulkanPipelineState();
  
    rdctype::array<rdctype::str> GetDisassemblyTargets();
    rdctype::str DisassembleShader(const ShaderReflection *refl, const char *target);
  
    rdctype::pair<ResourceId, rdctype::str> BuildCustomShader(const char *entry, const char *source,
                                                              const uint32_t compileFlags,
                                                              ShaderStage type);
    void FreeCustomShader(ResourceId id);
  
    rdctype::pair<ResourceId, rdctype::str> BuildTargetShader(const char *entry, const char *source,
                                                              const uint32_t compileFlags,
                                                              ShaderStage type);
    void ReplaceResource(ResourceId from, ResourceId to);
    void RemoveReplacement(ResourceId id);
    void FreeTargetResource(ResourceId id);
  
    FrameDescription GetFrameInfo();
    rdctype::array<DrawcallDescription> GetDrawcalls();
    rdctype::array<CounterResult> FetchCounters(const rdctype::array<GPUCounter> &counters);
    rdctype::array<GPUCounter> EnumerateCounters();
    CounterDescription DescribeCounter(GPUCounter counterID);
    rdctype::array<TextureDescription> GetTextures();
    rdctype::array<BufferDescription> GetBuffers();
    rdctype::array<rdctype::str> GetResolve(const rdctype::array<uint64_t> &callstack);
    rdctype::array<DebugMessage> GetDebugMessages();
  
    rdctype::array<PixelModification> PixelHistory(ResourceId target, uint32_t x, uint32_t y,
                                                   uint32_t slice, uint32_t mip, uint32_t sampleIdx,
                                                   CompType typeHint);
    ShaderDebugTrace *DebugVertex(uint32_t vertid, uint32_t instid, uint32_t idx, uint32_t instOffset,
                                  uint32_t vertOffset);
    ShaderDebugTrace *DebugPixel(uint32_t x, uint32_t y, uint32_t sample, uint32_t primitive);
    ShaderDebugTrace *DebugThread(const uint32_t groupid[3], const uint32_t threadid[3]);
    void FreeTrace(ShaderDebugTrace *trace);
  
    MeshFormat GetPostVSData(uint32_t instID, MeshDataStage stage);
  
    rdctype::array<EventUsage> GetUsage(ResourceId id);
  
    rdctype::array<byte> GetBufferData(ResourceId buff, uint64_t offset, uint64_t len);
    rdctype::array<byte> GetTextureData(ResourceId buff, uint32_t arrayIdx, uint32_t mip);
  
    bool SaveTexture(const TextureSave &saveData, const char *path);
  
    rdctype::array<ShaderVariable> GetCBufferVariableContents(ResourceId shader, const char *entryPoint,
                                                              uint32_t cbufslot, ResourceId buffer,
                                                              uint64_t offs);
  
    rdctype::array<WindowingSystem> GetSupportedWindowSystems();
  
    void ReplayLoop(WindowingSystem system, void *data, ResourceId texid);
    void CancelReplayLoop();
  
    ReplayOutput *CreateOutput(WindowingSystem, void *data, ReplayOutputType type);
  
    void ShutdownOutput(IReplayOutput *output);
    void Shutdown();
  
  private:
    ReplayStatus PostCreateInit(IReplayDriver *device);
  
    DrawcallDescription *GetDrawcallByEID(uint32_t eventID);
  
    IReplayDriver *GetDevice() { return m_pDevice; }
    FrameRecord m_FrameRecord;
    vector<DrawcallDescription *> m_Drawcalls;
  
    volatile int32_t m_ReplayLoopCancel = 0;
    volatile int32_t m_ReplayLoopFinished = 0;
  
    uint32_t m_EventID;
  
    D3D11Pipe::State m_D3D11PipelineState;
    D3D12Pipe::State m_D3D12PipelineState;
    GLPipe::State m_GLPipelineState;
    VKPipe::State m_VulkanPipelineState;
  
    std::vector<ReplayOutput *> m_Outputs;
  
    std::vector<BufferDescription> m_Buffers;
    std::vector<TextureDescription> m_Textures;
  
    IReplayDriver *m_pDevice;
  
    std::set<ResourceId> m_TargetResources;
    std::set<ResourceId> m_CustomShaders;
  
    friend struct ReplayOutput;
  };
  