gpu_thread.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  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 RendererBase;
  25. } // namespace VideoCore
  26. namespace VideoCommon::GPUThread {
  27. /// Command to signal to the GPU thread that processing has ended
  28. struct EndProcessingCommand final {};
  29. /// Command to signal to the GPU thread that a command list is ready for processing
  30. struct SubmitListCommand final {
  31. explicit SubmitListCommand(Tegra::CommandList&& entries_) : entries{std::move(entries_)} {}
  32. Tegra::CommandList entries;
  33. };
  34. /// Command to signal to the GPU thread that a cdma command list is ready for processing
  35. struct SubmitChCommandEntries final {
  36. explicit SubmitChCommandEntries(Tegra::ChCommandHeaderList&& entries_)
  37. : entries{std::move(entries_)} {}
  38. Tegra::ChCommandHeaderList entries;
  39. };
  40. /// Command to signal to the GPU thread that a swap buffers is pending
  41. struct SwapBuffersCommand final {
  42. explicit SwapBuffersCommand(std::optional<const Tegra::FramebufferConfig> framebuffer_)
  43. : framebuffer{std::move(framebuffer_)} {}
  44. std::optional<Tegra::FramebufferConfig> framebuffer;
  45. };
  46. /// Command to signal to the GPU thread to flush a region
  47. struct FlushRegionCommand final {
  48. explicit constexpr FlushRegionCommand(VAddr addr_, u64 size_) : addr{addr_}, size{size_} {}
  49. VAddr addr;
  50. u64 size;
  51. };
  52. /// Command to signal to the GPU thread to invalidate a region
  53. struct InvalidateRegionCommand final {
  54. explicit constexpr InvalidateRegionCommand(VAddr addr_, u64 size_) : addr{addr_}, size{size_} {}
  55. VAddr addr;
  56. u64 size;
  57. };
  58. /// Command to signal to the GPU thread to flush and invalidate a region
  59. struct FlushAndInvalidateRegionCommand final {
  60. explicit constexpr FlushAndInvalidateRegionCommand(VAddr addr_, u64 size_)
  61. : addr{addr_}, size{size_} {}
  62. VAddr addr;
  63. u64 size;
  64. };
  65. /// Command called within the gpu, to schedule actions after a command list end
  66. struct OnCommandListEndCommand final {};
  67. /// Command to make the gpu look into pending requests
  68. struct GPUTickCommand final {};
  69. using CommandData =
  70. std::variant<EndProcessingCommand, SubmitListCommand, SubmitChCommandEntries,
  71. SwapBuffersCommand, FlushRegionCommand, InvalidateRegionCommand,
  72. FlushAndInvalidateRegionCommand, OnCommandListEndCommand, GPUTickCommand>;
  73. struct CommandDataContainer {
  74. CommandDataContainer() = default;
  75. explicit CommandDataContainer(CommandData&& data_, u64 next_fence_)
  76. : data{std::move(data_)}, fence{next_fence_} {}
  77. CommandData data;
  78. u64 fence{};
  79. };
  80. /// Struct used to synchronize the GPU thread
  81. struct SynchState final {
  82. std::atomic_bool is_running{true};
  83. using CommandQueue = Common::MPSCQueue<CommandDataContainer>;
  84. CommandQueue queue;
  85. u64 last_fence{};
  86. std::atomic<u64> signaled_fence{};
  87. };
  88. /// Class used to manage the GPU thread
  89. class ThreadManager final {
  90. public:
  91. explicit ThreadManager(Core::System& system_, bool is_async_);
  92. ~ThreadManager();
  93. /// Creates and starts the GPU thread.
  94. void StartThread(VideoCore::RendererBase& renderer, Core::Frontend::GraphicsContext& context,
  95. Tegra::DmaPusher& dma_pusher, Tegra::CDmaPusher& cdma_pusher);
  96. /// Push GPU command entries to be processed
  97. void SubmitList(Tegra::CommandList&& entries);
  98. /// Push GPU CDMA command buffer entries to be processed
  99. void SubmitCommandBuffer(Tegra::ChCommandHeaderList&& entries);
  100. /// Swap buffers (render frame)
  101. void SwapBuffers(const Tegra::FramebufferConfig* framebuffer);
  102. /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
  103. void FlushRegion(VAddr addr, u64 size);
  104. /// Notify rasterizer that any caches of the specified region should be invalidated
  105. void InvalidateRegion(VAddr addr, u64 size);
  106. /// Notify rasterizer that any caches of the specified region should be flushed and invalidated
  107. void FlushAndInvalidateRegion(VAddr addr, u64 size);
  108. // Wait until the gpu thread is idle.
  109. void WaitIdle() const;
  110. void OnCommandListEnd();
  111. private:
  112. /// Pushes a command to be executed by the GPU thread
  113. u64 PushCommand(CommandData&& command_data);
  114. SynchState state;
  115. Core::System& system;
  116. std::thread thread;
  117. std::thread::id thread_id;
  118. const bool is_async;
  119. };
  120. } // namespace VideoCommon::GPUThread