gpu_thread.h 4.2 KB

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