gpu_thread.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. // Copyright 2019 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <atomic>
  6. #include <condition_variable>
  7. #include <mutex>
  8. #include <optional>
  9. #include <thread>
  10. #include <variant>
  11. #include "common/threadsafe_queue.h"
  12. #include "video_core/framebuffer_config.h"
  13. namespace Tegra {
  14. struct FramebufferConfig;
  15. class DmaPusher;
  16. } // namespace Tegra
  17. namespace Core {
  18. namespace Frontend {
  19. class GraphicsContext;
  20. }
  21. class System;
  22. } // namespace Core
  23. namespace VideoCore {
  24. class RasterizerInterface;
  25. class RendererBase;
  26. } // namespace VideoCore
  27. namespace VideoCommon::GPUThread {
  28. /// Command to signal to the GPU thread that processing has ended
  29. struct EndProcessingCommand final {};
  30. /// Command to signal to the GPU thread that a command list is ready for processing
  31. struct SubmitListCommand final {
  32. explicit SubmitListCommand(Tegra::CommandList&& entries_) : entries{std::move(entries_)} {}
  33. Tegra::CommandList entries;
  34. };
  35. /// Command to signal to the GPU thread that a swap buffers is pending
  36. struct SwapBuffersCommand final {
  37. explicit SwapBuffersCommand(std::optional<const Tegra::FramebufferConfig> framebuffer_)
  38. : framebuffer{std::move(framebuffer_)} {}
  39. std::optional<Tegra::FramebufferConfig> framebuffer;
  40. };
  41. /// Command to signal to the GPU thread to flush a region
  42. struct FlushRegionCommand final {
  43. explicit constexpr FlushRegionCommand(VAddr addr_, u64 size_) : addr{addr_}, size{size_} {}
  44. VAddr addr;
  45. u64 size;
  46. };
  47. /// Command to signal to the GPU thread to invalidate a region
  48. struct InvalidateRegionCommand final {
  49. explicit constexpr InvalidateRegionCommand(VAddr addr_, u64 size_) : addr{addr_}, size{size_} {}
  50. VAddr addr;
  51. u64 size;
  52. };
  53. /// Command to signal to the GPU thread to flush and invalidate a region
  54. struct FlushAndInvalidateRegionCommand final {
  55. explicit constexpr FlushAndInvalidateRegionCommand(VAddr addr_, u64 size_)
  56. : addr{addr_}, size{size_} {}
  57. VAddr addr;
  58. u64 size;
  59. };
  60. /// Command called within the gpu, to schedule actions after a command list end
  61. struct OnCommandListEndCommand final {};
  62. /// Command to make the gpu look into pending requests
  63. struct GPUTickCommand final {};
  64. using CommandData =
  65. std::variant<EndProcessingCommand, SubmitListCommand, SwapBuffersCommand, FlushRegionCommand,
  66. InvalidateRegionCommand, FlushAndInvalidateRegionCommand, OnCommandListEndCommand,
  67. GPUTickCommand>;
  68. struct CommandDataContainer {
  69. CommandDataContainer() = default;
  70. explicit CommandDataContainer(CommandData&& data_, u64 next_fence_, bool block_)
  71. : data{std::move(data_)}, fence{next_fence_}, block(block_) {}
  72. CommandData data;
  73. u64 fence{};
  74. bool block{};
  75. };
  76. /// Struct used to synchronize the GPU thread
  77. struct SynchState final {
  78. std::atomic_bool is_running{true};
  79. using CommandQueue = Common::SPSCQueue<CommandDataContainer>;
  80. std::mutex write_lock;
  81. CommandQueue queue;
  82. u64 last_fence{};
  83. std::atomic<u64> signaled_fence{};
  84. std::condition_variable cv;
  85. };
  86. /// Class used to manage the GPU thread
  87. class ThreadManager final {
  88. public:
  89. explicit ThreadManager(Core::System& system_, bool is_async_);
  90. ~ThreadManager();
  91. /// Creates and starts the GPU thread.
  92. void StartThread(VideoCore::RendererBase& renderer, Core::Frontend::GraphicsContext& context,
  93. Tegra::DmaPusher& dma_pusher);
  94. /// Push GPU command entries to be processed
  95. void SubmitList(Tegra::CommandList&& entries);
  96. /// Swap buffers (render frame)
  97. void SwapBuffers(const Tegra::FramebufferConfig* framebuffer);
  98. /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
  99. void FlushRegion(VAddr addr, u64 size);
  100. /// Notify rasterizer that any caches of the specified region should be invalidated
  101. void InvalidateRegion(VAddr addr, u64 size);
  102. /// Notify rasterizer that any caches of the specified region should be flushed and invalidated
  103. void FlushAndInvalidateRegion(VAddr addr, u64 size);
  104. // Stops the GPU execution and waits for the GPU to finish working
  105. void ShutDown();
  106. void OnCommandListEnd();
  107. private:
  108. /// Pushes a command to be executed by the GPU thread
  109. u64 PushCommand(CommandData&& command_data, bool block = false);
  110. Core::System& system;
  111. const bool is_async;
  112. VideoCore::RasterizerInterface* rasterizer = nullptr;
  113. SynchState state;
  114. std::thread thread;
  115. };
  116. } // namespace VideoCommon::GPUThread