/* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // the passes of a frame (decision K12 of the plan): a list in the fixed order the frame makes them, each pass saying which images // it uses and how. the barriers between the passes (sync2) are worked out from the state each image was left in, there's no // graph. each pass is a label for the captures and the validation layer (debug utils), and is timed on the gpu: the times // of the passes of the frames done go to the debug panel under the same names as the parts of the gpu frame of the opengl // renderer. when the device is lost, the log tells which passes of which frame were on the gpu #pragma once #include "rendering/vulkan14/vulkan14common.h" #include "rendering/vulkan14/vulkan14memory.h" namespace vk14 { class device; // an image a pass uses, and how struct image_use { VkImage image{VK_NULL_HANDLE}; VkImageAspectFlags aspect{VK_IMAGE_ASPECT_COLOR_BIT}; // where the state of the image is kept: by the image itself, or by the swapchain for its images image_state *state{nullptr}; VkImageLayout layout{VK_IMAGE_LAYOUT_UNDEFINED}; VkPipelineStageFlags2 stage{VK_PIPELINE_STAGE_2_NONE}; VkAccessFlags2 access{VK_ACCESS_2_NONE}; }; // the use of a vk14::image image_use use_of(image &Image, VkImageLayout Layout, VkPipelineStageFlags2 Stage, VkAccessFlags2 Access); // the barriers which bring the images from their states to the uses, the states updated void barriers(command_stream *Commands, std::vector const &Uses); // the barriers between two uses of the images in the states of the uses, made one after another (a rendering ended and begun again // by a walker, M2), without the states, which the main thread tracks void barriers_again(command_stream *Commands, std::vector const &Uses); class pass_list { public: pass_list() = default; pass_list(pass_list const &) = delete; pass_list &operator=(pass_list const &) = delete; ~pass_list(); bool create(device const &Device, std::uint32_t Frames, std::string &Reason); void destroy(); // the frame Frame (index of the frame in flight) is recorded to Commands from now on; Number counts the frames void begin_frame(command_stream *Commands, std::uint32_t Frame, std::uint64_t Number); // a pass: the barriers of its images, its label and the timestamp of its start void begin_pass(char const *Name, std::vector const &Uses = {}); void end_pass(); // the passes from here on go to Commands, for the compute queue (the async compute of M6), until end_async(); timed with queries of // their own, as their times overlap those of the passes of the graphics queue: they're shown apart, not in the total void begin_async(command_stream *Commands); void end_async(); void end_frame(); // the gpu times of the frame Frame, once the gpu is done with it (after the wait for its value of the timeline) void collect(std::uint32_t Frame); // the passes recorded in the frame done last, and the ones of the frame Number, for the report of a lost device std::string passes_of(std::uint64_t Number) const; // the checkpoints the gpu got to on Queue (device::checkpoints_enabled()): the pass of the frame whose start or end it reached last // at the top of the pipe (the work it took in) and at the bottom (the work done), for the report of a lost device std::string checkpoints(VkQueue Queue) const; // the gpu times (ms) of the parts of the frame, averaged, as the opengl renderer gives them: "name: x.xx ms" lines std::string info() const; double frame_ms() const { return m_framems; } private: struct frame_queries { VkQueryPool pool{VK_NULL_HANDLE}; std::vector names; std::uint32_t used{0}; // those of the compute queue, reset from the host VkQueryPool async_pool{VK_NULL_HANDLE}; std::vector async_names; std::uint32_t async_used{0}; std::uint64_t number{0}; bool recorded{false}; }; static constexpr std::uint32_t max_passes{32}; static constexpr std::uint32_t max_async{8}; VkDevice m_device{VK_NULL_HANDLE}; float m_period{1.f}; // ns per tick std::uint64_t m_mask{~0ull}; // the valid bits of the timestamps std::uint64_t m_asyncmask{~0ull}; // those of the compute queue std::vector m_frames; command_stream *m_commands{nullptr}; command_stream *m_graphics{nullptr}; // the stream of the graphics queue, while the passes go to the compute one bool m_async{false}; std::uint32_t m_frame{0}; int m_open{-1}; bool m_checkpoints{false}; std::uint64_t m_openmarker{0}; // the checkpoint of the start of the open pass // the name of the pass of a checkpoint std::string describe_checkpoint(std::uint64_t Marker) const; // averaged times of the parts, ms std::vector> m_times; std::vector> m_asynctimes; // of the compute queue double m_framems{0.0}; }; } // namespace vk14