gpu_thread.h 4.6 KB

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