gpu_thread.h 4.3 KB

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