gpu_thread.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #pragma once
  4. #include <atomic>
  5. #include <condition_variable>
  6. #include <mutex>
  7. #include <optional>
  8. #include <thread>
  9. #include <variant>
  10. #include "common/threadsafe_queue.h"
  11. #include "video_core/framebuffer_config.h"
  12. namespace Tegra {
  13. struct FramebufferConfig;
  14. namespace Control {
  15. class Scheduler;
  16. }
  17. } // namespace Tegra
  18. namespace Core {
  19. namespace Frontend {
  20. class GraphicsContext;
  21. }
  22. class System;
  23. } // namespace Core
  24. namespace VideoCore {
  25. class RasterizerInterface;
  26. class RendererBase;
  27. } // namespace VideoCore
  28. namespace VideoCommon::GPUThread {
  29. /// Command to signal to the GPU thread that a command list is ready for processing
  30. struct SubmitListCommand final {
  31. explicit SubmitListCommand(s32 channel_, Tegra::CommandList&& entries_)
  32. : channel{channel_}, entries{std::move(entries_)} {}
  33. s32 channel;
  34. Tegra::CommandList entries;
  35. };
  36. /// Command to signal to the GPU thread that a swap buffers is pending
  37. struct SwapBuffersCommand final {
  38. explicit SwapBuffersCommand(std::optional<const Tegra::FramebufferConfig> framebuffer_)
  39. : framebuffer{std::move(framebuffer_)} {}
  40. std::optional<Tegra::FramebufferConfig> framebuffer;
  41. };
  42. /// Command to signal to the GPU thread to flush a region
  43. struct FlushRegionCommand final {
  44. explicit constexpr FlushRegionCommand(VAddr addr_, u64 size_) : addr{addr_}, size{size_} {}
  45. VAddr addr;
  46. u64 size;
  47. };
  48. /// Command to signal to the GPU thread to invalidate a region
  49. struct InvalidateRegionCommand final {
  50. explicit constexpr InvalidateRegionCommand(VAddr addr_, u64 size_) : addr{addr_}, size{size_} {}
  51. VAddr addr;
  52. u64 size;
  53. };
  54. /// Command to signal to the GPU thread to flush and invalidate a region
  55. struct FlushAndInvalidateRegionCommand final {
  56. explicit constexpr FlushAndInvalidateRegionCommand(VAddr addr_, u64 size_)
  57. : addr{addr_}, size{size_} {}
  58. VAddr addr;
  59. u64 size;
  60. };
  61. /// Command called within the gpu, to schedule actions after a command list end
  62. struct OnCommandListEndCommand final {};
  63. /// Command to make the gpu look into pending requests
  64. struct GPUTickCommand final {};
  65. using CommandData =
  66. std::variant<std::monostate, SubmitListCommand, SwapBuffersCommand, FlushRegionCommand,
  67. InvalidateRegionCommand, FlushAndInvalidateRegionCommand, OnCommandListEndCommand,
  68. GPUTickCommand>;
  69. struct CommandDataContainer {
  70. CommandDataContainer() = default;
  71. explicit CommandDataContainer(CommandData&& data_, u64 next_fence_, bool block_)
  72. : data{std::move(data_)}, fence{next_fence_}, block(block_) {}
  73. CommandData data;
  74. u64 fence{};
  75. bool block{};
  76. };
  77. /// Struct used to synchronize the GPU thread
  78. struct SynchState final {
  79. using CommandQueue = Common::MPSCQueue<CommandDataContainer, true>;
  80. std::mutex write_lock;
  81. CommandQueue queue;
  82. u64 last_fence{};
  83. std::atomic<u64> signaled_fence{};
  84. std::condition_variable_any 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::Control::Scheduler& scheduler);
  94. /// Push GPU command entries to be processed
  95. void SubmitList(s32 channel, 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. void OnCommandListEnd();
  105. void TickGPU();
  106. private:
  107. /// Pushes a command to be executed by the GPU thread
  108. u64 PushCommand(CommandData&& command_data, bool block = false);
  109. Core::System& system;
  110. const bool is_async;
  111. VideoCore::RasterizerInterface* rasterizer = nullptr;
  112. SynchState state;
  113. std::jthread thread;
  114. };
  115. } // namespace VideoCommon::GPUThread