gpu_thread.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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/bounded_threadsafe_queue.h"
  11. #include "common/polyfill_thread.h"
  12. #include "video_core/framebuffer_config.h"
  13. namespace Tegra {
  14. struct FramebufferConfig;
  15. namespace Control {
  16. class Scheduler;
  17. }
  18. } // namespace Tegra
  19. namespace Core {
  20. namespace Frontend {
  21. class GraphicsContext;
  22. }
  23. class System;
  24. } // namespace Core
  25. namespace VideoCore {
  26. class RasterizerInterface;
  27. class RendererBase;
  28. } // namespace VideoCore
  29. namespace VideoCommon::GPUThread {
  30. /// Command to signal to the GPU thread that a command list is ready for processing
  31. struct SubmitListCommand final {
  32. explicit SubmitListCommand(s32 channel_, Tegra::CommandList&& entries_)
  33. : channel{channel_}, entries{std::move(entries_)} {}
  34. s32 channel;
  35. Tegra::CommandList 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(DAddr addr_, u64 size_) : addr{addr_}, size{size_} {}
  46. DAddr 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(DAddr addr_, u64 size_) : addr{addr_}, size{size_} {}
  52. DAddr 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(DAddr addr_, u64 size_)
  58. : addr{addr_}, size{size_} {}
  59. DAddr addr;
  60. u64 size;
  61. };
  62. /// Command to make the gpu look into pending requests
  63. struct GPUTickCommand final {};
  64. using CommandData =
  65. std::variant<std::monostate, SubmitListCommand, SwapBuffersCommand, FlushRegionCommand,
  66. InvalidateRegionCommand, FlushAndInvalidateRegionCommand, GPUTickCommand>;
  67. struct CommandDataContainer {
  68. CommandDataContainer() = default;
  69. explicit CommandDataContainer(CommandData&& data_, u64 next_fence_, bool block_)
  70. : data{std::move(data_)}, fence{next_fence_}, block(block_) {}
  71. CommandData data;
  72. u64 fence{};
  73. bool block{};
  74. };
  75. /// Struct used to synchronize the GPU thread
  76. struct SynchState final {
  77. using CommandQueue = Common::MPSCQueue<CommandDataContainer>;
  78. std::mutex write_lock;
  79. CommandQueue queue;
  80. u64 last_fence{};
  81. std::atomic<u64> signaled_fence{};
  82. std::condition_variable_any cv;
  83. };
  84. /// Class used to manage the GPU thread
  85. class ThreadManager final {
  86. public:
  87. explicit ThreadManager(Core::System& system_, bool is_async_);
  88. ~ThreadManager();
  89. /// Creates and starts the GPU thread.
  90. void StartThread(VideoCore::RendererBase& renderer, Core::Frontend::GraphicsContext& context,
  91. Tegra::Control::Scheduler& scheduler);
  92. /// Push GPU command entries to be processed
  93. void SubmitList(s32 channel, Tegra::CommandList&& entries);
  94. /// Swap buffers (render frame)
  95. void SwapBuffers(const Tegra::FramebufferConfig* framebuffer);
  96. /// Notify rasterizer that any caches of the specified region should be flushed to Switch memory
  97. void FlushRegion(DAddr addr, u64 size);
  98. /// Notify rasterizer that any caches of the specified region should be invalidated
  99. void InvalidateRegion(DAddr addr, u64 size);
  100. /// Notify rasterizer that any caches of the specified region should be flushed and invalidated
  101. void FlushAndInvalidateRegion(DAddr addr, u64 size);
  102. void TickGPU();
  103. private:
  104. /// Pushes a command to be executed by the GPU thread
  105. u64 PushCommand(CommandData&& command_data, bool block = false);
  106. Core::System& system;
  107. const bool is_async;
  108. VideoCore::RasterizerInterface* rasterizer = nullptr;
  109. SynchState state;
  110. std::jthread thread;
  111. };
  112. } // namespace VideoCommon::GPUThread